Skip to content

Commit

Permalink
List:
Browse files Browse the repository at this point in the history
- fixed wrong x/width bounds of alternating rows for multi-column lists (PR #939)
- Demo: added "alternating rows" checkboxes to "Data Components" page
  • Loading branch information
DevCharly committed Dec 18, 2024
1 parent 7027821 commit 80ba75f
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 31 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ FlatLaf Change Log

- CheckBox: Support styling indeterminate state of
[tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html).
(issue #919)
(PR #936; issue #919)
- List: Support for alternate row highlighting. (PR #939)
- Tree: Support for alternate row highlighting. (PR #903)
- Tree: Support wide cell renderer. (issue #922)
- Extras: `FlatSVGIcon` color filters now can access painting component to
Expand Down
25 changes: 12 additions & 13 deletions flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,24 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend
{
boolean isSelected = selModel.isSelectedIndex( row );

// paint alternating rows
if( alternateRowColor != null && row % 2 != 0 &&
!"ComboBox.list".equals( list.getName() ) ) // combobox does not support alternate row color
{
g.setColor( alternateRowColor );

float arc = UIScale.scale( selectionArc / 2f );
FlatUIUtils.paintSelection( (Graphics2D) g, rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height,
UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
}

// get renderer component
@SuppressWarnings( "unchecked" )
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
dataModel.getElementAt( row ), row, isSelected,
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );

//
// use smaller cell width if list is used in JFileChooser
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
int cx, cw;
if( isFileList ) {
Expand All @@ -323,18 +334,6 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend
cw = rowBounds.width;
}

// combobox does not support alternate row color
if( !"ComboBox.list".equals( list.getName() ) ) {
if( alternateRowColor != null && row % 2 != 0 ) {
g.setColor( alternateRowColor );

// paint respecting selection arc
float arc = UIScale.scale( selectionArc / 2f );
FlatUIUtils.paintSelection( (Graphics2D) g, 0, rowBounds.y, list.getWidth(), rowBounds.height,
UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
}
}

// rounded selection or selection insets
if( isSelected &&
!isFileList && // rounded selection is not supported for file list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import javax.swing.*;
import javax.swing.UIDefaults.ActiveValue;
import javax.swing.table.*;
import javax.swing.tree.*;
import com.formdev.flatlaf.FlatClientProperties;
Expand Down Expand Up @@ -65,6 +66,45 @@ class DataComponentsPanel
tree3.putClientProperty( FlatClientProperties.STYLE, "selectionInsets: 0,1,0,1; selectionArc: 6" );
}

private void listAlternatingRowsChanged() {
ActiveValue alternateRowColor = null;
if( listAlternatingRowsCheckBox.isSelected() ) {
alternateRowColor = table -> {
Color background = list1.getBackground();
return FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
}
UIManager.put( "List.alternateRowColor", alternateRowColor );
list1.updateUI();
list2.updateUI();
list3.updateUI();
}

private void treeWideSelectionChanged() {
boolean wideSelection = treeWideSelectionCheckBox.isSelected();
tree1.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
tree2.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
tree3.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
}

private void treeAlternatingRowsChanged() {
ActiveValue alternateRowColor = null;
if( treeAlternatingRowsCheckBox.isSelected() ) {
alternateRowColor = table -> {
Color background = tree1.getBackground();
return FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
}
UIManager.put( "Tree.alternateRowColor", alternateRowColor );
tree1.updateUI();
tree2.updateUI();
tree3.updateUI();
}

private void dndChanged() {
boolean dnd = dndCheckBox.isSelected();
DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION;
Expand Down Expand Up @@ -142,18 +182,20 @@ private void roundedSelectionChanged() {
}

private void alternatingRowsChanged() {
Color alternateRowColor = null;
ActiveValue alternateRowColor = null;
if( alternatingRowsCheckBox.isSelected() ) {
Color background = table1.getBackground();
alternateRowColor = FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
alternateRowColor = table -> {
Color background = table1.getBackground();
return FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
}
UIManager.put( "Table.alternateRowColor", alternateRowColor );
table1.repaint();
}

@SuppressWarnings( { "unchecked", "rawtypes" } )
@SuppressWarnings( { "rawtypes" } )
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel label1 = new JLabel();
Expand All @@ -166,13 +208,18 @@ private void initComponents() {
list3 = new JList<>();
JScrollPane scrollPane2 = new JScrollPane();
list2 = new JList<>();
JPanel listOptionsPanel = new JPanel();
listAlternatingRowsCheckBox = new JCheckBox();
JLabel treeLabel = new JLabel();
JScrollPane scrollPane3 = new JScrollPane();
tree1 = new JTree();
JScrollPane scrollPane7 = new JScrollPane();
tree3 = new JTree();
JScrollPane scrollPane4 = new JScrollPane();
tree2 = new JTree();
JPanel treeOptionsPanel = new JPanel();
treeWideSelectionCheckBox = new JCheckBox();
treeAlternatingRowsCheckBox = new JCheckBox();
JLabel tableLabel = new JLabel();
JScrollPane scrollPane5 = new JScrollPane();
table1 = new JTable();
Expand Down Expand Up @@ -273,6 +320,22 @@ private void initComponents() {
}
add(scrollPane2, "cell 3 1");

//======== listOptionsPanel ========
{
listOptionsPanel.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]"));

//---- listAlternatingRowsCheckBox ----
listAlternatingRowsCheckBox.setText("alternating rows");
listAlternatingRowsCheckBox.addActionListener(e -> listAlternatingRowsChanged());
listOptionsPanel.add(listAlternatingRowsCheckBox, "cell 0 0");
}
add(listOptionsPanel, "cell 4 1");

//---- treeLabel ----
treeLabel.setText("JTree:");
add(treeLabel, "cell 0 2,aligny top,growy 0");
Expand Down Expand Up @@ -334,6 +397,29 @@ private void initComponents() {
}
add(scrollPane4, "cell 3 2");

//======== treeOptionsPanel ========
{
treeOptionsPanel.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]0" +
"[]"));

//---- treeWideSelectionCheckBox ----
treeWideSelectionCheckBox.setText("wide selection");
treeWideSelectionCheckBox.setSelected(true);
treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged());
treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 0");

//---- treeAlternatingRowsCheckBox ----
treeAlternatingRowsCheckBox.setText("alternating rows");
treeAlternatingRowsCheckBox.addActionListener(e -> treeAlternatingRowsChanged());
treeOptionsPanel.add(treeAlternatingRowsCheckBox, "cell 0 1");
}
add(treeOptionsPanel, "cell 4 2");

//---- tableLabel ----
tableLabel.setText("JTable:");
add(tableLabel, "cell 0 3,aligny top,growy 0");
Expand Down Expand Up @@ -379,7 +465,7 @@ public boolean isCellEditable(int rowIndex, int columnIndex) {
{
TableColumnModel cm = table1.getColumnModel();
cm.getColumn(2).setCellEditor(new DefaultCellEditor(
new JComboBox(new DefaultComboBoxModel(new String[] {
new JComboBox<>(new DefaultComboBoxModel<>(new String[] {
"January",
"February",
"March",
Expand All @@ -394,7 +480,7 @@ public boolean isCellEditable(int rowIndex, int columnIndex) {
"December"
}))));
cm.getColumn(3).setCellEditor(new DefaultCellEditor(
new JComboBox(new DefaultComboBoxModel(new String[] {
new JComboBox<>(new DefaultComboBoxModel<>(new String[] {
"January",
"February",
"March",
Expand Down Expand Up @@ -513,9 +599,12 @@ public boolean isCellEditable(int rowIndex, int columnIndex) {
private JList<String> list1;
private JList<String> list3;
private JList<String> list2;
private JCheckBox listAlternatingRowsCheckBox;
private JTree tree1;
private JTree tree3;
private JTree tree2;
private JCheckBox treeWideSelectionCheckBox;
private JCheckBox treeAlternatingRowsCheckBox;
private JTable table1;
private JCheckBox roundedSelectionCheckBox;
private JCheckBox showHorizontalLinesCheckBox;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8"
JFDML JFormDesigner: "8.3" encoding: "UTF-8"

new FormModel {
contentType: "form/swing"
Expand Down Expand Up @@ -92,6 +92,25 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]"
} ) {
name: "listOptionsPanel"
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "listAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "treeLabel"
"text": "JTree:"
Expand Down Expand Up @@ -192,6 +211,36 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 2"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]0[]"
} ) {
name: "treeOptionsPanel"
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeWideSelectionCheckBox"
"text": "wide selection"
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeWideSelectionChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "tableLabel"
"text": "JTable:"
Expand Down
Loading

0 comments on commit 80ba75f

Please sign in to comment.