jdk/src/demo/share/jfc/TableExample/TableSorter.java
author martin
Thu, 30 Oct 2014 07:31:41 -0700
changeset 28059 e576535359cc
parent 25859 3317bb8137f4
permissions -rw-r--r--
8067377: My hobby: caning, then then canning, the the can-can Summary: Fix ALL the stutters! Reviewed-by: rriggs, mchung, lancea
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
     2
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * Redistribution and use in source and binary forms, with or without
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * modification, are permitted provided that the following conditions
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * are met:
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 *   - Redistributions of source code must retain the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *     notice, this list of conditions and the following disclaimer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 *   - Redistributions in binary form must reproduce the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 *     notice, this list of conditions and the following disclaimer in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 *     documentation and/or other materials provided with the distribution.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    15
 *   - Neither the name of Oracle nor the names of its
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *     contributors may be used to endorse or promote products derived
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 *     from this software without specific prior written permission.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
10292
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    32
/*
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    33
 * This source code is provided to illustrate the usage of a given feature
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    34
 * or technique and has been deliberately simplified. Additional steps
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    35
 * required for a production-quality application, such as security checks,
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    36
 * input validation and proper error handling, might not be present in
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    37
 * this sample code.
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    38
 */
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    39
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 8979
diff changeset
    40
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    41
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    42
import javax.swing.table.TableModel;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    43
import javax.swing.event.TableModelEvent;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    44
import java.awt.event.MouseAdapter;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    45
import java.awt.event.MouseEvent;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    46
import java.awt.event.InputEvent;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    47
import java.util.ArrayList;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    48
import java.util.Date;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    49
import java.util.List;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    50
import javax.swing.JTable;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    51
import javax.swing.table.JTableHeader;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    52
import javax.swing.table.TableColumnModel;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    53
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * A sorter for TableModels. The sorter has a model (conforming to TableModel)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * and itself implements TableModel. TableSorter does not store or copy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * the data in the TableModel, instead it maintains an array of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * integers which it keeps the same size as the number of rows in its
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * model. When the model changes it notifies the sorter that something
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * has changed eg. "rowsAdded" so that its internal array of integers
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * can be reallocated. As requests are made of the sorter (like
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * getValueAt(row, col) it redirects them to its model via the mapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * array. That way the TableSorter appears to hold another copy of the table
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * with the rows in a different order. The sorting algorthm used is stable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * which means that it does not move around rows when its comparison
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * function returns 0 to denote that they are equivalent.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * @author Philip Milne
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 */
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    71
@SuppressWarnings("serial")
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    72
public final class TableSorter extends TableMap {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    74
    int indexes[];
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    75
    List<Integer> sortingColumns = new ArrayList<Integer>();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    76
    boolean ascending = true;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    int compares;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    79
    public TableSorter() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
        indexes = new int[0]; // For consistency.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    83
    public TableSorter(TableModel model) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        setModel(model);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    87
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    public void setModel(TableModel model) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        super.setModel(model);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        reallocateIndexes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
    93
    public int compareRowsByColumn(int row1, int row2, int column) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        Class type = model.getColumnClass(column);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        TableModel data = model;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        // Check for nulls
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        Object o1 = data.getValueAt(row1, column);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        Object o2 = data.getValueAt(row2, column);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        // If both values are null return 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        if (o1 == null && o2 == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
            return 0;
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   105
        } else if (o1 == null) { // Define null less than everything.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            return -1;
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   107
        } else if (o2 == null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   111
        /* We copy all returned values from the getValue call in case
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   112
        an optimised model is reusing one object to return many values.
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   113
        The Number subclasses in the JDK are immutable and so will not be used
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   114
        in this way but other subclasses of Number might want to do this to save
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   115
        space and avoid unnecessary heap allocation.
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   116
         */
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   117
        if (type.getSuperclass() == java.lang.Number.class) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   118
            Number n1 = (Number) data.getValueAt(row1, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   119
            double d1 = n1.doubleValue();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   120
            Number n2 = (Number) data.getValueAt(row2, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   121
            double d2 = n2.doubleValue();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   122
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   123
            if (d1 < d2) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   124
                return -1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   125
            } else if (d1 > d2) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   126
                return 1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   127
            } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   128
                return 0;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   129
            }
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   130
        } else if (type == java.util.Date.class) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   131
            Date d1 = (Date) data.getValueAt(row1, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   132
            long n1 = d1.getTime();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   133
            Date d2 = (Date) data.getValueAt(row2, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   134
            long n2 = d2.getTime();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   136
            if (n1 < n2) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   137
                return -1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   138
            } else if (n1 > n2) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   139
                return 1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   140
            } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   141
                return 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   143
        } else if (type == String.class) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   144
            String s1 = (String) data.getValueAt(row1, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   145
            String s2 = (String) data.getValueAt(row2, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   146
            int result = s1.compareTo(s2);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   148
            if (result < 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   149
                return -1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   150
            } else if (result > 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   151
                return 1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   152
            } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   153
                return 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   155
        } else if (type == Boolean.class) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   156
            Boolean bool1 = (Boolean) data.getValueAt(row1, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   157
            boolean b1 = bool1.booleanValue();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   158
            Boolean bool2 = (Boolean) data.getValueAt(row2, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   159
            boolean b2 = bool2.booleanValue();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   160
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   161
            if (b1 == b2) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   162
                return 0;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   163
            } else if (b1) // Define false < true
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            {
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   165
                return 1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   166
            } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   167
                return -1;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
            }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   169
        } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   170
            Object v1 = data.getValueAt(row1, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   171
            String s1 = v1.toString();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   172
            Object v2 = data.getValueAt(row2, column);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   173
            String s2 = v2.toString();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   174
            int result = s1.compareTo(s2);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   176
            if (result < 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   177
                return -1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   178
            } else if (result > 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   179
                return 1;
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   180
            } else {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   181
                return 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   183
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   186
    public int compare(int row1, int row2) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        compares++;
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   188
        for (int level = 0; level < sortingColumns.size(); level++) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   189
            Integer column = sortingColumns.get(level);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   190
            int result = compareRowsByColumn(row1, row2, column.intValue());
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   191
            if (result != 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   192
                return ascending ? result : -result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   194
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   198
    public void reallocateIndexes() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        int rowCount = model.getRowCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        // Set up a new array of indexes with the right number of elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        // for the new data model.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        indexes = new int[rowCount];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        // Initialise with the identity mapping.
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   206
        for (int row = 0; row < rowCount; row++) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
            indexes[row] = row;
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   208
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   211
    @Override
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   212
    public void tableChanged(TableModelEvent e) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        System.out.println("Sorter: tableChanged");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        reallocateIndexes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        super.tableChanged(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   219
    public void checkModel() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        if (indexes.length != model.getRowCount()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            System.err.println("Sorter not informed of a change in model.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   225
    public void sort(Object sender) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        checkModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        compares = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        // n2sort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        // qsort(0, indexes.length-1);
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   231
        shuttlesort(indexes.clone(), indexes, 0, indexes.length);
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   232
        System.out.println("Compares: " + compares);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    public void n2sort() {
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   236
        for (int i = 0; i < getRowCount(); i++) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   237
            for (int j = i + 1; j < getRowCount(); j++) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                if (compare(indexes[i], indexes[j]) == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                    swap(i, j);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    // This is a home-grown implementation which we have not had time
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    // to research - it may perform poorly in some circumstances. It
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    // requires twice the space of an in-place algorithm and makes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    // NlogN assigments shuttling the values between the two
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    // arrays. The number of compares appears to vary between N-1 and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    // NlogN depending on the initial order but the main reason for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    // using it here is that, unlike qsort, it is stable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    public void shuttlesort(int from[], int to[], int low, int high) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        if (high - low < 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   256
        int middle = (low + high) / 2;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        shuttlesort(to, from, low, middle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        shuttlesort(to, from, middle, high);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        int p = low;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        int q = middle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        /* This is an optional short-cut; at each recursive call,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        check to see if the elements in this subset are already
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        ordered.  If so, no further comparisons are needed; the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        sub-array can just be copied.  The array must be copied rather
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        than assigned otherwise sister calls in the recursion might
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        get out of sinc.  When the number of elements is three they
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        are partitioned so that the first set, [low, mid), has one
28059
e576535359cc 8067377: My hobby: caning, then then canning, the the can-can
martin
parents: 25859
diff changeset
   270
        element and the second, [mid, high), has two. We skip the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        optimisation when the number of elements is three or less as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        the first compare in the normal merge will produce the same
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        sequence of steps. This optimisation seems to be worthwhile
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        for partially ordered lists but some analysis is needed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        find out how the performance drops to Nlog(N) as the initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        order diminishes - it may drop very quickly.  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   278
        if (high - low >= 4 && compare(from[middle - 1], from[middle]) <= 0) {
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   279
            System.arraycopy(from, low, to, low, high - low);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        // A normal merge.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   285
        for (int i = low; i < high; i++) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                to[i] = from[p++];
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   288
            } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                to[i] = from[q++];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    public void swap(int i, int j) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        int tmp = indexes[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        indexes[i] = indexes[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        indexes[j] = tmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
    // The mapping only affects the contents of the data rows.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
    // Pass all requests to these rows through the mapping array: "indexes".
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   302
    @Override
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   303
    public Object getValueAt(int aRow, int aColumn) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        checkModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        return model.getValueAt(indexes[aRow], aColumn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   308
    @Override
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   309
    public void setValueAt(Object aValue, int aRow, int aColumn) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        checkModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        model.setValueAt(aValue, indexes[aRow], aColumn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    public void sortByColumn(int column) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        sortByColumn(column, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    public void sortByColumn(int column, boolean ascending) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        this.ascending = ascending;
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   320
        sortingColumns.clear();
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   321
        sortingColumns.add(column);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        sort(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        super.tableChanged(new TableModelEvent(this));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    // There is no-where else to put this.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    // Add a mouse listener to the Table to trigger a table sort
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    // when a column heading is clicked in the JTable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    public void addMouseListenerToHeaderInTable(JTable table) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        final TableSorter sorter = this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        final JTable tableView = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        tableView.setColumnSelectionAllowed(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        MouseAdapter listMouseListener = new MouseAdapter() {
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   334
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   335
            @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            public void mouseClicked(MouseEvent e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                TableColumnModel columnModel = tableView.getColumnModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                int viewColumn = columnModel.getColumnIndexAtX(e.getX());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                int column = tableView.convertColumnIndexToModel(viewColumn);
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   340
                if (e.getClickCount() == 1 && column != -1) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                    System.out.println("Sorting ...");
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   342
                    int shiftPressed = e.getModifiers() & InputEvent.SHIFT_MASK;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                    boolean ascending = (shiftPressed == 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                    sorter.sortByColumn(column, ascending);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                }
8979
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   346
            }
30050c8aea19 7027701: /jfc/TableExample demo needs to be improved
mrkam
parents: 5506
diff changeset
   347
        };
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        JTableHeader th = tableView.getTableHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        th.addMouseListener(listMouseListener);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
}