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 }