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;
}
}
}