package com.onaro.util.jfc; import com.onaro.util.jfc.tables.SortingHeaderRenderer; import javax.swing.*; import javax.swing.table.TableModel; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; /** * A sorted JTable letting the user choose the sorting column and * order by clicking the table header. */ public class SortedTable extends JTable implements EncapsulatingTable { private static final long serialVersionUID = 1L; /** * The sorted table model that does the actual sorting. */ private SortedTableModel sortedModel; private SortingHeaderRenderer headerRenderer; /** * Constructs a sorted table for the given model. * * @param sourceModel the data model that is sorted and than is displayed * in the table */ public SortedTable(TableModel sourceModel) { super(sourceModel); getTableHeader().addMouseListener(new SortAndWidthMouseListener()); headerRenderer = new SortingHeaderRenderer(sortedModel); // sourted model is initilized bu the super constructor getTableHeader().setDefaultRenderer(headerRenderer); } /** * Constructs a table with the defualt model. */ public SortedTable() { this(null); } /** * Sets the new model as the source model of the sorted table model. * * @param newModel the new table model */ public void setModel(TableModel newModel) { assert newModel != null : "The data model cannot be null"; //$NON-NLS-1$ sortedModel = new SortedTableModel(newModel); if (headerRenderer != null) headerRenderer.setSortingInfo(sortedModel); super.setModel(sortedModel); } /** * Returns the TableModel that provides the data displayed by this * JTable which is the sorted model. * * @return the TableModel that provides the data displayed by this JTable */ public TableModel getModel() { return sortedModel; } /** * Gets the encapsulated table-model. * * @return the encapsulated table-model */ public TableModel getEncapsulatedTableModel() { return sortedModel.getSourceModel(); } /** * Sets the encapsulated table-model. * * @param tableModel the encapsulated table-model */ public void setEncapsulatedTableModel(TableModel tableModel) { setModel(tableModel); } /** * Get the row number in the encapsulated model of a row in the sorting * model. * * @param row row number in the sorting model * @return row number in the encapsulated model or -1 the row cannot be * mapped into a row in the encapsulated model */ public int getRowInEncapsulatedModel(int row) { return sortedModel.translateSortedToSource(row); } /** * Sets the sorting column and order. * * @param sortingColumn the new sorting column * @param ascending true id the sorting order is ascending */ public void setSortingColumn(int sortingColumn, boolean ascending) { sortedModel.setSortingColumn(sortingColumn, ascending); } /** * Returns the index of the sorting column, or NO_SORTING_COLUMN * if the DATA is not sorted on any column. * * @return the column used for sorting */ public int getSortingColumn() { return sortedModel.getSortingColumn(); } /** * Returns true if the DATA is sorted in ascending order, and false otherwise. * * @return true if the DATA is sorted in ascending order, and false otherwise */ public boolean getAscending() { return sortedModel.getAscending(); } /** * Adds a listener to the model that is notified each the sorting has changed. * * @param l the listener */ public void addSortingListener(SortedTableModel.SortingListener l) { sortedModel.addSortingListener(l); } /** * Removes a listener from the list that is notified each the sorting had changed. * * @param l the listener */ public void removeSortingListener(SortedTableModel.SortingListener l) { sortedModel.removeSortingListener(l); } /** * A mouse click listener with the table header which changes the * sorting according to the user clicks on the column headers. */ private class SortAndWidthMouseListener extends MouseAdapter { public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1 ) { Point point = e.getPoint(); int edge = 4; Point leftPoint = new Point(point.x-edge, point.y); Point rightPoint = new Point(point.x+edge, point.y); int col = tableHeader.columnAtPoint(point); int colLeft = tableHeader.columnAtPoint(leftPoint); int colRight = tableHeader.columnAtPoint(rightPoint); boolean isEdge = col != colLeft || col != colRight; if( e.getClickCount() == 1 && !isEdge) { int colInModel = convertColumnIndexToModel(col); if (sortedModel.getSortingColumn() != colInModel) { sortedModel.setSortingColumn(colInModel, true); } else { sortedModel.setAscending(!sortedModel.getAscending()); } tableHeader.repaint(); } else if( e.getClickCount() == 2 && isEdge && colLeft != -1 ) { TableUtils.setColumnPreferredWidth(colLeft, SortedTable.this); } } } } }