package de.muntjak.tinylookandfeel.table; import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; import javax.swing.JTable; import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.UIResource; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import javax.swing.table.TableModel; import de.muntjak.tinylookandfeel.Theme; import de.muntjak.tinylookandfeel.TinyTableHeaderUI; /** * This TableCellRenderer is installed on the table header in * TinyTableHeaderUI.installDefaults() so we can change the border on rollover * and show an arrow icon for sorted columns. * * @author Hans Bickel */ @SuppressWarnings ( { "all" } ) public class TinyTableHeaderRenderer extends DefaultTableCellRenderer implements UIResource { private static final Icon arrowNo = new Arrow ( true, -1 ); // arrows array will be lazily filled private static final Icon [][] arrows = new Icon [ 2 ] [ 4 ]; private int [] horizontalAlignments; public TinyTableHeaderRenderer () { setHorizontalAlignment ( CENTER ); setHorizontalTextPosition ( LEFT ); } /** * Sets horizontal alignments of renderers where an index in the argument * array corresponds to a column index. * * @param alignments array of the following constants defined in * <code>SwingConstants</code>: <code>LEFT</code>, * <code>CENTER</code>, <code>RIGHT</code>, * <code>LEADING</code> (the default for text-only labels) or * <code>TRAILING</code>. */ public void setHorizontalAlignments ( int [] alignments ) { horizontalAlignments = alignments; } public Component getTableCellRendererComponent ( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) { LookAndFeel laf = UIManager.getLookAndFeel (); if ( laf == null || !"TinyLookAndFeel".equals ( laf.getName () ) ) { if ( table != null ) { JTableHeader header = table.getTableHeader (); if ( header != null ) { setBackground ( header.getBackground () ); setForeground ( header.getForeground () ); setFont ( header.getFont () ); } } setIcon ( null ); setText ( ( value == null ) ? "" : value.toString () ); setBorder ( UIManager.getBorder ( "TableHeader.cellBorder" ) ); return this; } boolean isRolloverColumn = false; Icon icon = arrowNo; int sortingDirection = SortableTableData.SORT_ASCENDING; int priority = -1; boolean paintArrow = false; if ( table != null ) { JTableHeader header = table.getTableHeader (); if ( header != null ) { Object o = header .getClientProperty ( TinyTableHeaderUI.ROLLOVER_COLUMN_KEY ); if ( o != null ) { int rolloverColumn = ( ( Integer ) o ).intValue (); if ( rolloverColumn == column ) { isRolloverColumn = true; } } o = header.getClientProperty ( TinyTableHeaderUI.SORTED_COLUMN_KEY ); if ( o != null ) { int sc[] = ( int [] ) o; priority = -1; for ( int i = 0 ; i < sc.length ; i++ ) { if ( sc [ i ] == column ) { priority = i; } } if ( priority > -1 ) { paintArrow = true; o = header .getClientProperty ( TinyTableHeaderUI.SORTING_DIRECTION_KEY ); if ( o != null ) { int [] sd = ( int [] ) o; sortingDirection = sd [ priority ]; } } } if ( isRolloverColumn ) { setBackground ( Theme.tableHeaderRolloverBackColor [ Theme.style ] .getColor () ); } else { setBackground ( header.getBackground () ); } setForeground ( header.getForeground () ); setFont ( header.getFont () ); } TableModel model = table.getModel (); if ( model instanceof SortableTableData ) { if ( paintArrow ) { int pri = Math.min ( 3, priority ); if ( sortingDirection == SortableTableData.SORT_ASCENDING ) { if ( arrows [ 0 ] [ pri ] == null ) { arrows [ 0 ] [ pri ] = new Arrow ( false, priority ); } icon = arrows [ 0 ] [ pri ]; } else { if ( arrows [ 1 ] [ pri ] == null ) { arrows [ 1 ] [ pri ] = new Arrow ( true, priority ); } icon = arrows [ 1 ] [ pri ]; } } else { int modelColumn = table.getColumnModel ().getColumn ( column ) .getModelIndex (); if ( ! ( ( SortableTableData ) model ) .isColumnSortable ( modelColumn ) ) { icon = null; } } } else { icon = null; setToolTipText ( null ); } } setIcon ( icon ); setText ( ( value == null ) ? "" : value.toString () ); if ( isRolloverColumn ) { setBorder ( UIManager.getBorder ( "TableHeader.cellRolloverBorder" ) ); } else { setBorder ( UIManager.getBorder ( "TableHeader.cellBorder" ) ); } int modelColumn = table.getColumnModel ().getColumn ( column ) .getModelIndex (); if ( horizontalAlignments != null && horizontalAlignments.length > modelColumn ) { setHorizontalAlignment ( horizontalAlignments [ modelColumn ] ); } return this; } private static class Arrow implements Icon { private static final int height = 11; private boolean descending; private int priority; public Arrow ( boolean descending, int priority ) { this.descending = descending; this.priority = Math.min ( 3, priority ); } public void paintIcon ( Component c, Graphics g, int x, int y ) { if ( priority == -1 ) return; // empty icon // In a compound sort, make each successive triangle // smaller than the previous one int dx = priority; int dy = ( height - 5 + priority ) / 2; g.translate ( x + dx, y + dy ); g.setColor ( Theme.tableHeaderArrowColor [ Theme.style ].getColor () ); if ( descending ) { switch ( priority ) { case 0 : g.drawLine ( 4, 4, 4, 4 ); g.drawLine ( 3, 3, 5, 3 ); g.drawLine ( 2, 2, 6, 2 ); g.drawLine ( 1, 1, 7, 1 ); g.drawLine ( 0, 0, 8, 0 ); break; case 1 : g.drawLine ( 3, 3, 3, 3 ); g.drawLine ( 2, 2, 4, 2 ); g.drawLine ( 1, 1, 5, 1 ); g.drawLine ( 0, 0, 6, 0 ); break; case 2 : g.drawLine ( 2, 2, 2, 2 ); g.drawLine ( 1, 1, 3, 1 ); g.drawLine ( 0, 0, 4, 0 ); break; case 3 : default : g.drawLine ( 1, 1, 1, 1 ); g.drawLine ( 0, 0, 2, 0 ); break; } } else { switch ( priority ) { case 0 : g.drawLine ( 4, 0, 4, 0 ); g.drawLine ( 3, 1, 5, 1 ); g.drawLine ( 2, 2, 6, 2 ); g.drawLine ( 1, 3, 7, 3 ); g.drawLine ( 0, 4, 8, 4 ); break; case 1 : g.drawLine ( 3, 0, 3, 0 ); g.drawLine ( 2, 1, 4, 1 ); g.drawLine ( 1, 2, 5, 2 ); g.drawLine ( 0, 3, 6, 3 ); break; case 2 : g.drawLine ( 2, 0, 2, 0 ); g.drawLine ( 1, 1, 3, 1 ); g.drawLine ( 0, 2, 4, 2 ); break; case 3 : default : g.drawLine ( 1, 0, 1, 0 ); g.drawLine ( 0, 1, 2, 1 ); break; } } g.translate ( - ( x + dx ), - ( y + dy ) ); } public int getIconWidth () { return 9; } public int getIconHeight () { return height; } } }