Skip to content

Commit 58dbcce

Browse files
committed
Table: optionally paint alternating rows below table if table is smaller than scroll pane (issue #504)
1 parent 90de14d commit 58dbcce

5 files changed

Lines changed: 107 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ FlatLaf Change Log
55

66
#### New features and improvements
77

8+
- Table: Optionally paint alternating rows below table if table is smaller than
9+
scroll pane. Set UI value `Table.paintOutsideAlternateRows` to `true`.
10+
Requires that `Table.alternateRowColor` is set to a color. (issue #504)
811
- ToggleButton: Made the underline placement of tab-style toggle buttons
912
configurable. (PR #530; issue #529)
1013
- Added spanish translation. (PR #525)
@@ -155,7 +158,7 @@ FlatLaf Change Log
155158
- Possibility to hide window title bar icon (for single window set client
156159
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
157160
value `TitlePane.showIcon` to `false`).
158-
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
161+
- OptionPane: Hide window title bar icon by default. Can be made visibly by
159162
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
160163
- No longer show the Java "duke/cup" icon if no window icon image is set.
161164
(issue #416)

flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
* @uiDefault Table.intercellSpacing Dimension
8181
* @uiDefault Table.selectionInactiveBackground Color
8282
* @uiDefault Table.selectionInactiveForeground Color
83+
* @uiDefault Table.paintOutsideAlternateRows boolean
8384
*
8485
* <!-- FlatTableCellBorder -->
8586
*
@@ -95,7 +96,7 @@
9596
*/
9697
public class FlatTableUI
9798
extends BasicTableUI
98-
implements StyleableUI
99+
implements StyleableUI, FlatViewportUI.ViewportPainter
99100
{
100101
protected boolean showHorizontalLines;
101102
protected boolean showVerticalLines;
@@ -421,4 +422,38 @@ protected boolean hideLastVerticalLine() {
421422
? (viewport != rowHeader)
422423
: (viewport == rowHeader || rowHeader == null);
423424
}
425+
426+
/** @since 2.3 */
427+
@Override
428+
public void paintViewport( Graphics g, JComponent c, JViewport viewport ) {
429+
int viewportWidth = viewport.getWidth();
430+
int viewportHeight = viewport.getHeight();
431+
432+
// fill viewport background in same color as table background
433+
if( viewport.isOpaque() ) {
434+
g.setColor( table.getBackground() );
435+
g.fillRect( 0, 0, viewportWidth, viewportHeight );
436+
}
437+
438+
// paint alternating empty rows
439+
boolean paintOutside = UIManager.getBoolean( "Table.paintOutsideAlternateRows" );
440+
Color alternateColor;
441+
if( paintOutside && (alternateColor = UIManager.getColor( "Table.alternateRowColor" )) != null ) {
442+
g.setColor( alternateColor );
443+
444+
int rowCount = table.getRowCount();
445+
446+
// paint alternating empty rows below the table
447+
int tableHeight = table.getHeight();
448+
if( tableHeight < viewportHeight ) {
449+
int tableWidth = table.getWidth();
450+
int rowHeight = table.getRowHeight();
451+
452+
for( int y = tableHeight, row = rowCount; y < viewportHeight; y += rowHeight, row++ ) {
453+
if( row % 2 != 0 )
454+
g.fillRect( 0, y, tableWidth, rowHeight );
455+
}
456+
}
457+
}
458+
}
424459
}

flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatViewportUI.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
import java.awt.Component;
2020
import java.awt.Graphics;
21+
import java.lang.reflect.Method;
2122
import javax.swing.JComponent;
22-
import javax.swing.JTable;
2323
import javax.swing.JViewport;
2424
import javax.swing.plaf.ComponentUI;
2525
import javax.swing.plaf.basic.BasicViewportUI;
@@ -43,15 +43,28 @@ public static ComponentUI createUI( JComponent c ) {
4343
}
4444

4545
@Override
46-
public void update( Graphics g, JComponent c ) {
46+
public void paint( Graphics g, JComponent c ) {
47+
super.paint( g, c );
48+
4749
Component view = ((JViewport)c).getView();
48-
if( c.isOpaque() && view instanceof JTable ) {
49-
// paint viewport background in same color as table background
50-
g.setColor( view.getBackground() );
51-
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
50+
if( view instanceof JComponent ) {
51+
try {
52+
Method m = view.getClass().getMethod( "getUI" );
53+
Object ui = m.invoke( view );
54+
if( ui instanceof ViewportPainter )
55+
((ViewportPainter)ui).paintViewport( g, (JComponent) view, (JViewport) c );
56+
} catch( Exception ex ) {
57+
// ignore
58+
}
59+
}
60+
}
61+
62+
//---- interface ViewportPainter ------------------------------------------
5263

53-
paint( g, c );
54-
} else
55-
super.update( g, c );
64+
/**
65+
* @since 2.3
66+
*/
67+
public interface ViewportPainter {
68+
void paintViewport( Graphics g, JComponent c, JViewport viewport );
5669
}
5770
}

flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,16 @@ private void focusCellEditorChanged() {
336336
table.setSurrendersFocusOnKeystroke( focusCellEditorCheckBox.isSelected() );
337337
}
338338

339+
private void alternatingRowsChanged() {
340+
UIManager.put( "Table.alternateRowColor", alternatingRowsCheckBox.isSelected() ? Color.orange : null );
341+
table1ScrollPane.repaint();
342+
}
343+
344+
private void paintOutsideAlternateRowsChanged() {
345+
UIManager.put( "Table.paintOutsideAlternateRows", paintOutsideAlternateRowsCheckBox.isSelected() ? true : null );
346+
table1ScrollPane.repaint();
347+
}
348+
339349
private void treeRendererChanged() {
340350
Object sel = treeRendererComboBox.getSelectedItem();
341351
if( !(sel instanceof String) )
@@ -493,8 +503,10 @@ private void initComponents() {
493503
focusCellEditorCheckBox = new JCheckBox();
494504
showVerticalLinesCheckBox = new JCheckBox();
495505
columnSelectionCheckBox = new JCheckBox();
506+
alternatingRowsCheckBox = new JCheckBox();
496507
intercellSpacingCheckBox = new JCheckBox();
497508
rowHeaderCheckBox = new JCheckBox();
509+
paintOutsideAlternateRowsCheckBox = new JCheckBox();
498510
redGridColorCheckBox = new JCheckBox();
499511
tableHeaderButtonCheckBox = new JCheckBox();
500512

@@ -875,6 +887,11 @@ public void mouseClicked(MouseEvent e) {
875887
columnSelectionCheckBox.addActionListener(e -> columnSelectionChanged());
876888
tableOptionsPanel.add(columnSelectionCheckBox, "cell 1 2");
877889

890+
//---- alternatingRowsCheckBox ----
891+
alternatingRowsCheckBox.setText("alternating rows");
892+
alternatingRowsCheckBox.addActionListener(e -> alternatingRowsChanged());
893+
tableOptionsPanel.add(alternatingRowsCheckBox, "cell 2 2");
894+
878895
//---- intercellSpacingCheckBox ----
879896
intercellSpacingCheckBox.setText("intercell spacing");
880897
intercellSpacingCheckBox.addActionListener(e -> intercellSpacingChanged());
@@ -885,6 +902,11 @@ public void mouseClicked(MouseEvent e) {
885902
rowHeaderCheckBox.addActionListener(e -> rowHeaderChanged());
886903
tableOptionsPanel.add(rowHeaderCheckBox, "cell 1 3");
887904

905+
//---- paintOutsideAlternateRowsCheckBox ----
906+
paintOutsideAlternateRowsCheckBox.setText("outside alternating rows");
907+
paintOutsideAlternateRowsCheckBox.addActionListener(e -> paintOutsideAlternateRowsChanged());
908+
tableOptionsPanel.add(paintOutsideAlternateRowsCheckBox, "cell 2 3");
909+
888910
//---- redGridColorCheckBox ----
889911
redGridColorCheckBox.setText("red grid color");
890912
redGridColorCheckBox.addActionListener(e -> redGridColorChanged());
@@ -927,8 +949,10 @@ public void mouseClicked(MouseEvent e) {
927949
private JCheckBox focusCellEditorCheckBox;
928950
private JCheckBox showVerticalLinesCheckBox;
929951
private JCheckBox columnSelectionCheckBox;
952+
private JCheckBox alternatingRowsCheckBox;
930953
private JCheckBox intercellSpacingCheckBox;
931954
private JCheckBox rowHeaderCheckBox;
955+
private JCheckBox paintOutsideAlternateRowsCheckBox;
932956
private JCheckBox redGridColorCheckBox;
933957
private JCheckBox tableHeaderButtonCheckBox;
934958
// JFormDesigner - End of variables declaration //GEN-END:variables

flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
1+
JFDML JFormDesigner: "7.0.5.0.404" Java: "17.0.2" encoding: "UTF-8"
22

33
new FormModel {
44
contentType: "form/swing"
@@ -485,6 +485,16 @@ new FormModel {
485485
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
486486
"value": "cell 1 2"
487487
} )
488+
add( new FormComponent( "javax.swing.JCheckBox" ) {
489+
name: "alternatingRowsCheckBox"
490+
"text": "alternating rows"
491+
auxiliary() {
492+
"JavaCodeGenerator.variableLocal": false
493+
}
494+
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "alternatingRowsChanged", false ) )
495+
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
496+
"value": "cell 2 2"
497+
} )
488498
add( new FormComponent( "javax.swing.JCheckBox" ) {
489499
name: "intercellSpacingCheckBox"
490500
"text": "intercell spacing"
@@ -505,6 +515,16 @@ new FormModel {
505515
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
506516
"value": "cell 1 3"
507517
} )
518+
add( new FormComponent( "javax.swing.JCheckBox" ) {
519+
name: "paintOutsideAlternateRowsCheckBox"
520+
"text": "outside alternating rows"
521+
auxiliary() {
522+
"JavaCodeGenerator.variableLocal": false
523+
}
524+
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "paintOutsideAlternateRowsChanged", false ) )
525+
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
526+
"value": "cell 2 3"
527+
} )
508528
add( new FormComponent( "javax.swing.JCheckBox" ) {
509529
name: "redGridColorCheckBox"
510530
"text": "red grid color"

0 commit comments

Comments
 (0)