View Javadoc

    1   /*
    2    * $Id: SortFilterModel.java 471756 2006-11-06 15:01:43Z husted $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *  http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21  package org.apache.struts2.components.table;
    22
    23  import java.awt.event.MouseAdapter;
    24  import java.awt.event.MouseEvent;
    25  import java.util.ArrayList;
    26  import java.util.Collections;
    27
    28  import javax.swing.JTable;
    29  import javax.swing.event.TableModelEvent;
    30  import javax.swing.event.TableModelListener;
    31  import javax.swing.table.TableModel;
    32
    33
    34  /***
    35   */
    36  public class SortFilterModel extends AbstractFilterModel implements TableModelListener, SortableTableModel {
    37
    38      private static final long serialVersionUID = 2214225803442793597L;
    39
    40      private ArrayList rows = new ArrayList();
    41
    42      /***
    43       * These are just here to implement the interface
    44       */
    45      private String _sortDirection = NONE;
    46      private boolean dirty = true;
    47      private int sortColumn = -1;
    48
    49
    50      public SortFilterModel(TableModel tm) {
    51          super(tm);
    52          setModel(tm);
    53      }
    54
    55
    56      public boolean isCellEditable(int r, int c) {
    57          if ((rows.size() > 0) && (r < rows.size())) {
    58              return model.isCellEditable(((Row) rows.get(r)).index, c);
    59          }
    60
    61          return false;
    62      }
    63
    64      public void setModel(TableModel tm) {
    65          super.setModel(tm);
    66          rows.ensureCapacity(model.getRowCount());
    67          model.addTableModelListener(this);
    68          sortColumn = -1;
    69          dirty = true;
    70          refresh();
    71      }
    72
    73      public int getSortedColumnNumber() {
    74          return sortColumn;
    75      }
    76
    77      public String getSortedDirection(int columnNumber) {
    78          if (getSortedColumnNumber() < 0) {
    79              return NONE;
    80          }
    81
    82          return _sortDirection;
    83      }
    84
    85      public void setValueAt(Object aValue, int r, int c) {
    86          if ((rows.size() > 0) && (r < rows.size())) {
    87              model.setValueAt(aValue, ((Row) rows.get(r)).index, c);
    88          }
    89      }
    90
    91      /* compute the moved row for the three methods that access
    92         model elements
    93      */
    94      public Object getValueAt(int r, int c) {
    95          if ((rows.size() > 0) && (r < rows.size())) {
    96              return model.getValueAt(((Row) rows.get(r)).index, c);
    97          }
    98
    99          return null;
    100     }
    101
    102     public void addMouseListener(final JTable table) {
    103         table.getTableHeader().addMouseListener(new MouseAdapter() {
    104             public void mouseClicked(MouseEvent event) {
    105                 // check for double click
    106                 if (event.getClickCount() < 2) {
    107                     return;
    108                 }
    109
    110                 // find column of click and
    111                 int tableColumn = table.columnAtPoint(event.getPoint());
    112
    113                 // translate to table model index and sort
    114                 int modelColumn = table.convertColumnIndexToModel(tableColumn);
    115                 sort(modelColumn);
    116             }
    117         });
    118     }
    119
    120     public void removeRow(int rowNum) throws ArrayIndexOutOfBoundsException, IllegalStateException {
    121         int mappedRow = ((Row) rows.get(rowNum)).index;
    122         super.removeRow(mappedRow);
    123     }
    124
    125     public void sort(int columnNumber, String direction) {
    126         _sortDirection = ASC;
    127         dirty = true;
    128         sort(columnNumber);
    129
    130         if (DESC.equals(direction)) {
    131             sort(columnNumber);
    132             _sortDirection = DESC;
    133         }
    134     }
    135
    136     /***
    137      * Implements the TableModelListener interface to receive
    138      * notifications of * changes to the table model. SortFilterModel needs
    139      * to receive events for adding and removing rows.
    140      */
    141     public void tableChanged(TableModelEvent e) {
    142         dirty = true;
    143         refresh();
    144         fireTableChanged(e);
    145     }
    146
    147     protected void refresh() {
    148         rows.clear();
    149
    150         for (int i = 0; i < model.getRowCount(); i++) {
    151             rows.add(new Row(i));
    152         }
    153
    154         if (dirty && (sortColumn > -1)) {
    155             sort(sortColumn);
    156         }
    157     }
    158
    159     protected void sort(int c) {
    160         boolean sorted = (sortColumn == c);
    161         sortColumn = c;
    162
    163         if (dirty || !sorted) {
    164             Collections.sort(rows);
    165             dirty = false;
    166         } else {
    167             Collections.reverse(rows);
    168         }
    169
    170         fireTableDataChanged();
    171     }
    172
    173
    174     /* this inner class holds the index of the model row
    175      * Rows are compared by looking at the model row entries
    176      * in the sort column
    177      */
    178     private class Row implements Comparable {
    179         public int index;
    180
    181         public Row(int index) {
    182             this.index = index;
    183         }
    184
    185         public int compareTo(Object other) {
    186             Row otherRow = (Row) other;
    187             Object a = model.getValueAt(index, sortColumn);
    188             Object b = model.getValueAt(otherRow.index, sortColumn);
    189
    190             boolean areTheyCompareable = (a instanceof Comparable && b instanceof Comparable && (a.getClass() == b.getClass()));
    191
    192             if (areTheyCompareable) {
    193                 return ((Comparable) a).compareTo((Comparable) b);
    194             } else {
    195                 return a.toString().compareTo(b.toString());
    196             }
    197         }
    198     }
    199 }