001/*
002 * Created on 25.02.2011
003 *
004 */
005package org.jdesktop.swingx.table;
006
007import java.awt.Component;
008import java.util.Collections;
009import java.util.List;
010
011import javax.swing.JTable;
012import javax.swing.event.TableModelEvent;
013import javax.swing.table.TableCellRenderer;
014import javax.swing.table.TableColumn;
015import javax.swing.table.TableColumnModel;
016
017/**
018 * Collection of utility methods for J/X/Table.
019 * 
020 * @author Jeanette Winzenburg, Berlin
021 */
022public class TableUtilities {
023    
024    
025    /**
026     * Returns a boolean indication whether the event represents a
027     * dataChanged type.
028     * 
029     * @param e the event to examine.
030     * @return true if the event is of type dataChanged, false else.
031     */
032    public static boolean isDataChanged(TableModelEvent e) {
033        if (e == null)
034            return false;
035        return e.getType() == TableModelEvent.UPDATE && e.getFirstRow() == 0
036                && e.getLastRow() == Integer.MAX_VALUE;
037    }
038
039    /**
040     * Returns a boolean indication whether the event represents a
041     * update type.
042     * 
043     * @param e the event to examine.
044     * @return true if the event is a true update, false
045     *         otherwise.
046     */
047    public static boolean isUpdate(TableModelEvent e) {
048        if (isStructureChanged(e))
049            return false;
050        return e.getType() == TableModelEvent.UPDATE
051                && e.getLastRow() < Integer.MAX_VALUE;
052    }
053
054    /**
055     * Returns a boolean indication whether the event represents a
056     * insert type.
057     * 
058     * @param e the event to examine
059     * @return true if the event is of type insert, false otherwise.
060     */
061    public static boolean isInsert(TableModelEvent e) {
062        if (e == null) return false;
063        return TableModelEvent.INSERT == e.getType();
064    }
065
066
067    /**
068     * Returns a boolean indication whether the event represents a
069     * structureChanged type.
070     * 
071     * @param e the event to examine.
072     * @return true if the event is of type structureChanged or null, false
073     *         else.
074     */
075    public static boolean isStructureChanged(TableModelEvent e) {
076        return e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW;
077    }
078
079
080
081    /**
082     * Returns the preferred height for the given row. It loops
083     * across all visible columns and returns the maximal pref height of
084     * the rendering component. Falls back to the table's base rowheight, i
085     * f there are no columns or the renderers
086     * max is zeor.<p>
087     * 
088     * @param table the table which provides the renderers, must not be null
089     * @param row the index of the row in view coordinates
090     * @return the preferred row height of
091     * @throws NullPointerException if table is null.
092     * @throws IndexOutOfBoundsException if the row is not a valid row index
093     */
094    public static int getPreferredRowHeight(JTable table, int row) {
095        int pref = 0;
096        for (int column = 0; column < table.getColumnCount(); column++) {
097            TableCellRenderer renderer = table.getCellRenderer(row, column);
098            Component comp = table.prepareRenderer(renderer, row, column);
099            pref = Math.max(pref, comp.getPreferredSize().height);
100        }
101        return pref > 0 ? pref : table.getRowHeight();
102    }
103    
104    /**
105     * 
106     * @param table the table which provides the renderers, must not be null
107     * @param row the index of the row in view coordinates
108     * @throws NullPointerException if table is null.
109     * @throws IndexOutOfBoundsException if the row is not a valid row index
110     */
111    public static void setPreferredRowHeight(JTable table, int row) {
112        int prefHeight = getPreferredRowHeight(table, row);
113        table.setRowHeight(row, prefHeight);
114    }
115
116    /**
117     * Sets preferred row heights for all visible rows. 
118     * 
119     * @param table the table to set row heights to
120     * @throws NullPointerException if no table installed.
121     */
122    public static void setPreferredRowHeights(JTable table) {
123        // care about visible rows only
124        for (int row = 0; row < table.getRowCount(); row++) {
125            setPreferredRowHeight(table, row);
126        }
127    }
128    
129    /**
130     * Returns an array containing the ordinals of the given values of an Enum.<p>
131     * 
132     * Convience for clients which define TableColumns as Enums (Issue #1304-swingx).
133     * 
134     * @param values the enums to map to its ordinals
135     * @return an array of ordinals, guaranteed to be not null
136     */
137    public static int[] ordinalsOf(Enum<?>... values) {
138        int[] cols = new int[values.length];
139        for (int i = 0; i < values.length; i++) {
140            cols[i] = values[i].ordinal();
141        }
142        return cols;
143    }
144    
145
146    /**
147     * Removes all columns of the given column model. Includes hidden
148     * columns as indicated by the includesHidden flag, the flag has no 
149     * effect if the model is not of type TableColumnModelExt.<p>
150     * 
151     * @param model the column model to remove all columns from.
152     * @param includeHidden indicates whether hidden columns should be 
153     *   removed as well, has no effect if model is not of type TableColumnModelExt.
154     */
155    /*
156     * Stand-in instead of fixing of issue http://java.net/jira/browse/SWINGX-1407
157     */
158    public static void clear(TableColumnModel model, boolean includeHidden) {
159        if (model instanceof TableColumnModelExt) {
160            clear(model, ((TableColumnModelExt) model).getColumns(includeHidden));
161        } else {
162            clear(model, Collections.list(model.getColumns()));
163        }
164    }
165
166    private static void clear(TableColumnModel model, List<TableColumn> columns) {
167        for (TableColumn tableColumn : columns) {
168            model.removeColumn(tableColumn);
169        }
170    }
171
172    private TableUtilities() {}
173}