Skip to content

Commit b57f598

Browse files
committed
Custom renderers support.
1 parent e224eab commit b57f598

File tree

6 files changed

+119
-2
lines changed

6 files changed

+119
-2
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ New features:
2424
- Generic support for L&Fs (it means they're not reimplemented, they're used as delegates for rendering)
2525
- Easy to use table model API
2626
- Table header cells highlighting on mouse over
27+
- Table header cells etching on mouse dragging
2728
- Table cells spans API to merge cells inside a table itself (not in a header)
2829
- Drawing of dragged columns group in a table itself (not only in a header)
30+
- Custom header cell renderer support
2931
- Partial test coverage
3032
- Setting custom rowspan. Rowspan is calculated automatically in a greedy way, but sometimes such a picture is needed (and it can't be calculated automatically):
3133

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.quinto.swing.table.view;
2+
3+
import java.awt.Component;
4+
import javax.swing.JTable;
5+
import org.quinto.swing.table.model.IModelFieldGroup;
6+
7+
public interface CustomTableHeaderRenderer {
8+
/**
9+
* Warning: originalComponent may be shared within a level by different cells.
10+
* If rendering of one cell changes originalComponent's properties
11+
* then rendering of other cells should restore original properties (or set them to appropriate values).
12+
* @param originalComponent
13+
* @param table
14+
* @param value
15+
* @param isSelected
16+
* @param hasFocus
17+
* @param isDragged
18+
* @param row
19+
* @param viewColumn
20+
* @param modelColumn
21+
* @param dataField
22+
* @return
23+
*/
24+
public Component getTableCellRendererComponent( Component originalComponent, JTable table, Object value, boolean isSelected, boolean hasFocus, boolean isDragged, int row, int viewColumn, int modelColumn, IModelFieldGroup dataField );
25+
}

src/org/quinto/swing/table/view/JBroTableHeaderUI.java

+38-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.swing.table.TableColumn;
3636
import org.apache.log4j.Logger;
3737
import org.quinto.swing.table.model.IModelFieldGroup;
38+
import org.quinto.swing.table.model.ModelData;
3839

3940
public class JBroTableHeaderUI extends BasicTableHeaderUI {
4041
private static final Logger LOGGER = Logger.getLogger( JBroTableHeaderUI.class );
@@ -50,6 +51,7 @@ public class JBroTableHeaderUI extends BasicTableHeaderUI {
5051
private boolean updating;
5152
private ComponentUI headerDelegate;
5253
private ReverseBorder lastBorder;
54+
private CustomTableHeaderRenderer customRenderer;
5355

5456
public JBroTableHeaderUI( JBroTable table ) {
5557
this.table = table;
@@ -66,6 +68,14 @@ void updateLookAndFeel() {
6668
}
6769
updating = false;
6870
}
71+
72+
public CustomTableHeaderRenderer getCustomRenderer() {
73+
return customRenderer;
74+
}
75+
76+
public void setCustomRenderer( CustomTableHeaderRenderer customRenderer ) {
77+
this.customRenderer = customRenderer;
78+
}
6979

7080
public JBroTableHeader getHeader() {
7181
return ( JBroTableHeader )header;
@@ -401,7 +411,11 @@ private void paintCell( Graphics g, Rectangle cellRect, JBroTableColumn group )
401411
boolean parentUIdeterminesRolloverColumnItself = hasParentUI( renderer );
402412
boolean rollover = parentUIdeterminesRolloverColumnItself ? group == getHeader().getDraggedGroup() : group == selectedColumn;
403413
table.setCurrentLevel( group.getY() );
404-
Component comp = renderer.getTableCellRendererComponent( table, group.getHeaderValue(), rollover, rollover, group.getY(), getTableColumnModel().getColumnRelativeIndex( group ) );
414+
Object value = group.getHeaderValue();
415+
int row = group.getY();
416+
JBroTableColumnModel tcm = getTableColumnModel();
417+
int viewColumn = tcm.getColumnRelativeIndex( group );
418+
Component comp = renderer.getTableCellRendererComponent( table, value, rollover, rollover, row, viewColumn );
405419
table.setCurrentLevel( null );
406420
if ( !parentUIdeterminesRolloverColumnItself && comp instanceof JComponent && group == getHeader().getDraggedGroup() ) {
407421
Border border = ( ( JComponent )comp ).getBorder();
@@ -411,6 +425,29 @@ private void paintCell( Graphics g, Rectangle cellRect, JBroTableColumn group )
411425
( ( JComponent )comp ).setBorder( lastBorder );
412426
}
413427
}
428+
if ( customRenderer != null ) {
429+
IModelFieldGroup dataField = null;
430+
int modelColumn = group.getModelIndex();
431+
ModelData data = table.getData();
432+
if ( data != null ) {
433+
if ( modelColumn >= 0 && data.getFields() != null && modelColumn < data.getFields().length )
434+
dataField = data.getFields()[ modelColumn ];
435+
else {
436+
int coords[] = data.getIndexOfModelFieldGroup( String.valueOf( group.getIdentifier() ) );
437+
int level = coords[ 1 ];
438+
int col = coords[ 0 ];
439+
if ( level >= 0 && col >= 0 ) {
440+
List< IModelFieldGroup[] > fields = data.getFieldGroups();
441+
if ( fields.size() > level ) {
442+
IModelFieldGroup levelFields[] = fields.get( level );
443+
if ( levelFields.length > col )
444+
dataField = levelFields[ col ];
445+
}
446+
}
447+
}
448+
}
449+
comp = customRenderer.getTableCellRendererComponent( comp, table, value, rollover, rollover, group == getHeader().getDraggedGroup(), row, viewColumn, modelColumn, dataField );
450+
}
414451
paintCell( g, comp, cellRect );
415452
}
416453

src/org/quinto/swing/table/view/ReverseBorder.java

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import java.awt.Insets;
77
import javax.swing.border.Border;
88

9+
/**
10+
* A border that rotates a delegate border by 180 degrees.
11+
* <p>It causes a raised bevel border to be lowered and vice versa.</p>
12+
*/
913
public class ReverseBorder implements Border {
1014
private final Border delegate;
1115

test/org/quinto/swing/table/view/JBroTableColumnModelShowcase.java

+49
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import com.sun.java.swing.plaf.motif.MotifLookAndFeel;
44
import com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel;
55
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
6+
import java.awt.Color;
7+
import java.awt.Component;
68
import java.awt.FlowLayout;
9+
import java.awt.Font;
10+
import java.awt.Graphics;
11+
import java.awt.GridLayout;
712
import java.awt.Toolkit;
813
import java.awt.event.ActionEvent;
914
import java.awt.event.ActionListener;
@@ -12,8 +17,11 @@
1217
import java.util.Collections;
1318
import javax.swing.JButton;
1419
import javax.swing.JFrame;
20+
import javax.swing.JLabel;
21+
import javax.swing.JPanel;
1522
import javax.swing.JScrollPane;
1623
import javax.swing.JTable;
24+
import javax.swing.SwingConstants;
1725
import javax.swing.UIManager;
1826
import javax.swing.UnsupportedLookAndFeelException;
1927
import javax.swing.plaf.metal.DefaultMetalTheme;
@@ -23,6 +31,7 @@
2331
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
2432
import javax.swing.table.TableColumn;
2533
import org.apache.log4j.Logger;
34+
import org.quinto.swing.table.model.IModelFieldGroup;
2635
import org.quinto.swing.table.model.ModelData;
2736
import org.quinto.swing.table.model.ModelField;
2837
import org.quinto.swing.table.model.ModelFieldGroup;
@@ -39,6 +48,8 @@ public class JBroTableColumnModelShowcase {
3948

4049
public static void main( String args[] ) {
4150
Utils.initSimpleConsoleLogger();
51+
52+
// Look & Feel switcher.
4253
Method m;
4354
try {
4455
m = Toolkit.class.getDeclaredMethod( "setDesktopProperty", String.class, Object.class );
@@ -104,6 +115,8 @@ else if ( laf == 4 ) {
104115
}
105116
};
106117
lafChanger.actionPerformed( null );
118+
119+
// Table model.
107120
int colCnt = 10;
108121
int rowCnt = 10;
109122
ModelField fields[] = new ModelField[ colCnt ];
@@ -127,11 +140,47 @@ else if ( laf == 4 ) {
127140
rows[ i ].setValue( j, i == j ? "sort me" : String.valueOf( ( char )( 'A' + j ) ) + i );
128141
}
129142
data.setRows( rows );
143+
144+
// Table view.
130145
table = new JBroTable( data );
131146
table.setAutoCreateRowSorter( true );
147+
table.getTableHeader().getUI().setCustomRenderer( new CustomTableHeaderRenderer() {
148+
@Override
149+
public Component getTableCellRendererComponent( final Component originalComponent, JTable table, Object value, boolean isSelected, boolean hasFocus, boolean isDragged, int row, int viewColumn, int modelColumn, IModelFieldGroup dataField ) {
150+
if ( dataField == null || !( originalComponent instanceof JLabel ) )
151+
return originalComponent;
152+
JLabel ret = ( JLabel )originalComponent;
153+
String fieldName = dataField.getIdentifier();
154+
// "GC" cell is right aligned. Other cells are centered.
155+
ret.setHorizontalAlignment( "GC".equals( fieldName ) ? SwingConstants.RIGHT : SwingConstants.CENTER );
156+
// "D" cell caption is written in bold. Other captions have plain font.
157+
ret.setFont( ret.getFont().deriveFont( "D".equals( fieldName ) ? Font.BOLD : Font.PLAIN ) );
158+
// "B" cell would be half-transparent red with Windows L&F (not classic).
159+
// Note that background is reset on each call by underlying renderer so there's no need to reset background for other cells.
160+
// Properties like alignment and font should be reset on each call if they were changed before.
161+
if ( "B".equals( fieldName ) && !originalComponent.getClass().getName().contains( "DefaultTableCellHeaderRenderer" ) )
162+
ret.setBackground( new Color( 220, 50, 50, 50 ) );
163+
// "C" cell would be half-transparent red.
164+
if ( "C".equals( fieldName ) ) {
165+
JPanel p = new JPanel( new GridLayout( 1, 1 ) ) {
166+
@Override
167+
public void paint( Graphics g ) {
168+
super.paint( g );
169+
g.setColor( new Color( 220, 50, 50, 50 ) );
170+
g.fillRect( 0, 0, getWidth(), getHeight() );
171+
}
172+
};
173+
p.add( ret );
174+
return p;
175+
}
176+
return ret;
177+
}
178+
} );
132179
System.out.println( table.getColumnModel() );
133180
for ( TableColumn tc : Collections.list( table.getColumnModel().getColumns() ) )
134181
System.out.println( tc.getHeaderValue() );
182+
183+
// Frame.
135184
frame = new JFrame( "Testing" );
136185
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
137186
frame.setLayout( new FlowLayout() );

version.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
project.version=1.0.1
1+
project.version=1.0.3

0 commit comments

Comments
 (0)