Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree: support wide cell renderer #935

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FlatLaf Change Log
#### New features and improvements

- 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
implement component state based color mappings. (issue #906)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1410,13 +1410,23 @@ public interface FlatClientProperties
//---- JTree --------------------------------------------------------------

/**
* Override if a tree shows a wide selection. Default is {@code true}.
* Specifies whether tree shows a wide selection. Default is {@code true}.
* <p>
* <strong>Component</strong> {@link javax.swing.JTree}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String TREE_WIDE_SELECTION = "JTree.wideSelection";

/**
* Specifies whether tree uses a wide cell renderer. Default is {@code false}.
* <p>
* <strong>Component</strong> {@link javax.swing.JTree}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @since 3.6
*/
String TREE_WIDE_CELL_RENDERER = "JTree.wideCellRenderer";

/**
* Specifies whether tree item selection is painted. Default is {@code true}.
* If set to {@code false}, then the tree cell renderer is responsible for painting selection.
Expand Down
21 changes: 21 additions & 0 deletions flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
* @uiDefault Tree.selectionInsets Insets
* @uiDefault Tree.selectionArc int
* @uiDefault Tree.wideSelection boolean
* @uiDefault Tree.wideCellRenderer boolean
* @uiDefault Tree.showCellFocusIndicator boolean
* @uiDefault Tree.showDefaultIcons boolean
*
Expand Down Expand Up @@ -146,6 +147,7 @@ public class FlatTreeUI
/** @since 3 */ @Styleable protected Insets selectionInsets;
/** @since 3 */ @Styleable protected int selectionArc;
@Styleable protected boolean wideSelection;
/** @since 3.6 */ @Styleable protected boolean wideCellRenderer;
@Styleable protected boolean showCellFocusIndicator;
/** @since 3 */ protected boolean showDefaultIcons;

Expand Down Expand Up @@ -198,6 +200,7 @@ protected void installDefaults() {
selectionInsets = UIManager.getInsets( "Tree.selectionInsets" );
selectionArc = UIManager.getInt( "Tree.selectionArc" );
wideSelection = UIManager.getBoolean( "Tree.wideSelection" );
wideCellRenderer = UIManager.getBoolean( "Tree.wideCellRenderer" );
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
showDefaultIcons = UIManager.getBoolean( "Tree.showDefaultIcons" );

Expand Down Expand Up @@ -314,6 +317,7 @@ protected PropertyChangeListener createPropertyChangeListener() {
if( e.getSource() == tree ) {
switch( e.getPropertyName() ) {
case TREE_WIDE_SELECTION:
case TREE_WIDE_CELL_RENDERER:
case TREE_PAINT_SELECTION:
HiDPIUtils.repaint( tree );
break;
Expand Down Expand Up @@ -584,6 +588,18 @@ protected void paintRow( Graphics g, Rectangle clipBounds, Insets insets, Rectan
UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
}

// update bounds for wide cell renderer
if( isWideSelection() && isWideCellRenderer() ) {
Rectangle wideBounds = new Rectangle( bounds );
if( tree.getComponentOrientation().isLeftToRight() )
wideBounds.width = tree.getWidth() - bounds.x - insets.right;
else {
wideBounds.x = insets.left;
wideBounds.width = bounds.x + bounds.width - insets.left;
}
bounds = wideBounds;
}

// do not paint row if editing
if( isEditing ) {
// paint wide selection
Expand Down Expand Up @@ -808,6 +824,11 @@ protected boolean isWideSelection() {
return clientPropertyBoolean( tree, TREE_WIDE_SELECTION, wideSelection );
}

/** @since 3.6 */
protected boolean isWideCellRenderer() {
return clientPropertyBoolean( tree, TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}

protected boolean isPaintSelection() {
return clientPropertyBoolean( tree, TREE_PAINT_SELECTION, paintSelection );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@ Tree.rendererMargins = 1,2,1,2
Tree.selectionInsets = 0,0,0,0
Tree.selectionArc = 0
Tree.wideSelection = true
Tree.wideCellRenderer = false
Tree.repaintWholeRow = true
Tree.paintLines = false
Tree.showCellFocusIndicator = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ void tree() {
"selectionInsets", Insets.class,
"selectionArc", int.class,
"wideSelection", boolean.class,
"wideCellRenderer", boolean.class,
"showCellFocusIndicator", boolean.class,

"paintSelection", boolean.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ void tree() {
testInsets( c, ui, "selectionInsets", 1,2,3,4 );
testInteger( c, ui, "selectionArc", 123 );
testBoolean( c, ui, "wideSelection", true );
testBoolean( c, ui, "wideCellRenderer", true );
testBoolean( c, ui, "showCellFocusIndicator", true );

testBoolean( c, ui, "paintSelection", false );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ void tree() {
ui.applyStyle( "selectionInsets: 1,2,3,4" );
ui.applyStyle( "selectionArc: 8" );
ui.applyStyle( "wideSelection: true" );
ui.applyStyle( "wideCellRenderer: true" );
ui.applyStyle( "showCellFocusIndicator: true" );

ui.applyStyle( "paintSelection: false" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,37 @@ public class FlatTree
implements FlatComponentExtension, FlatStyleableComponent
{
/**
* Returns if the tree shows a wide selection
* Returns whether tree shows a wide selection
*/
public boolean isWideSelection() {
return getClientPropertyBoolean( TREE_WIDE_SELECTION, "Tree.wideSelection" );
}

/**
* Sets if the tree shows a wide selection
* Specifies whether tree shows a wide selection
*/
public void setWideSelection( boolean wideSelection ) {
putClientProperty( TREE_WIDE_SELECTION, wideSelection );
}

/**
* Returns whether tree uses a wide cell renderer.
*
* @since 3.6
*/
public boolean isWideCellRenderer() {
return getClientPropertyBoolean( TREE_WIDE_CELL_RENDERER, "Tree.wideCellRenderer" );
}

/**
* Specifies whether tree uses a wide cell renderer.
*
* @since 3.6
*/
public void setWideCellRenderer( boolean wideCellRenderer ) {
putClientProperty( TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}

/**
* Returns whether tree item selection is painted. Default is {@code true}.
* If set to {@code false}, then the tree cell renderer is responsible for painting selection.
Expand Down
1 change: 1 addition & 0 deletions flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,7 @@ Tree.showDefaultIcons false
Tree.textBackground #46494b HSL 204 3 28 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI

Expand Down
1 change: 1 addition & 0 deletions flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,7 @@ Tree.showDefaultIcons false
Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI

Expand Down
1 change: 1 addition & 0 deletions flatlaf-testing/dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,7 @@ Tree.showDefaultIcons false
Tree.textBackground #282828 HSL 0 0 16 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI

Expand Down
1 change: 1 addition & 0 deletions flatlaf-testing/dumps/uidefaults/FlatMacLightLaf_1.8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,7 @@ Tree.showDefaultIcons false
Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI

Expand Down
1 change: 1 addition & 0 deletions flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,7 @@ Tree.showDefaultIcons false
Tree.textBackground #fff0ff HSL 300 100 97 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.formdev.flatlaf.testing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
Expand All @@ -32,6 +33,7 @@
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Supplier;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.TableModelEvent;
Expand Down Expand Up @@ -497,48 +499,23 @@ private void treeRendererChanged() {
if( !(sel instanceof String) )
return;

JTree[] trees = { tree1, tree2, xTree1 };
Supplier<TreeCellRenderer> creator;
switch( (String) sel ) {
case "default":
for( JTree tree : trees )
tree.setCellRenderer( new DefaultTreeCellRenderer() );
break;

case "defaultSubclass":
for( JTree tree : trees )
tree.setCellRenderer( new TestDefaultTreeCellRenderer() );
break;

case "defaultWithIcons":
for( JTree tree : trees )
tree.setCellRenderer( new TestDefaultWithIconsTreeCellRenderer() );
break;

case "defaultWithIcon":
for( JTree tree : trees )
tree.setCellRenderer( new TestDefaultWithIconTreeCellRenderer() );
break;

case "label":
for( JTree tree : trees )
tree.setCellRenderer( new TestLabelTreeCellRenderer() );
break;

case "swingxDefault":
for( JTree tree : trees )
tree.setCellRenderer( new DefaultTreeRenderer() );
break;

case "jideCheckBox":
for( JTree tree : trees )
tree.setCellRenderer( new CheckBoxTreeCellRenderer( new DefaultTreeCellRenderer() ) );
break;

case "jideStyled":
for( JTree tree : trees )
tree.setCellRenderer( new StyledTreeCellRenderer() );
break;
default:
case "default": creator = DefaultTreeCellRenderer::new; break;
case "defaultSubclass": creator = TestDefaultTreeCellRenderer::new; break;
case "defaultWithIcons": creator = TestDefaultWithIconsTreeCellRenderer::new; break;
case "defaultWithIcon": creator = TestDefaultWithIconTreeCellRenderer::new; break;
case "label": creator = TestLabelTreeCellRenderer::new; break;
case "wide": creator = TestWideTreeCellRenderer::new; break;
case "swingxDefault": creator = DefaultTreeRenderer::new; break;
case "jideCheckBox": creator = () -> new CheckBoxTreeCellRenderer( new DefaultTreeCellRenderer() ); break;
case "jideStyled": creator = StyledTreeCellRenderer::new; break;
}

JTree[] trees = { tree1, tree2, xTree1 };
for( JTree tree : trees )
tree.setCellRenderer( creator.get() );
}

private void treeWideSelectionChanged() {
Expand All @@ -547,6 +524,12 @@ private void treeWideSelectionChanged() {
tree.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
}

private void treeWideCellRendererChanged() {
boolean wideCellRenderer = treeWideCellRendererCheckBox.isSelected();
for( JTree tree : allTrees )
tree.putClientProperty( FlatClientProperties.TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}

private void treePaintSelectionChanged() {
boolean paintSelection = treePaintSelectionCheckBox.isSelected();
for( JTree tree : allTrees )
Expand Down Expand Up @@ -691,6 +674,7 @@ private void initComponents() {
JLabel treeRendererLabel = new JLabel();
treeRendererComboBox = new JComboBox<>();
treeWideSelectionCheckBox = new JCheckBox();
treeWideCellRendererCheckBox = new JCheckBox();
treePaintSelectionCheckBox = new JCheckBox();
treePaintLinesCheckBox = new JCheckBox();
treeRedLinesCheckBox = new JCheckBox();
Expand Down Expand Up @@ -1088,6 +1072,7 @@ public void mouseClicked(MouseEvent e) {
"defaultWithIcons",
"defaultWithIcon",
"label",
"wide",
"swingxDefault",
"jideCheckBox",
"jideStyled"
Expand All @@ -1100,6 +1085,11 @@ public void mouseClicked(MouseEvent e) {
treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged());
treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 1");

//---- treeWideCellRendererCheckBox ----
treeWideCellRendererCheckBox.setText("wide cell renderer");
treeWideCellRendererCheckBox.addActionListener(e -> treeWideCellRendererChanged());
treeOptionsPanel.add(treeWideCellRendererCheckBox, "cell 0 1");

//---- treePaintSelectionCheckBox ----
treePaintSelectionCheckBox.setText("paint selection");
treePaintSelectionCheckBox.setSelected(true);
Expand Down Expand Up @@ -1266,6 +1256,7 @@ public void mouseClicked(MouseEvent e) {
private JPanel treeOptionsPanel;
private JComboBox<String> treeRendererComboBox;
private JCheckBox treeWideSelectionCheckBox;
private JCheckBox treeWideCellRendererCheckBox;
private JCheckBox treePaintSelectionCheckBox;
private JCheckBox treePaintLinesCheckBox;
private JCheckBox treeRedLinesCheckBox;
Expand Down Expand Up @@ -1794,6 +1785,32 @@ public Component getTreeCellRendererComponent( JTree tree, Object value, boolean
}
}

//---- class TestLabelTreeCellRenderer ------------------------------------

private static class TestWideTreeCellRenderer
extends JPanel
implements TreeCellRenderer
{
private final JLabel label = new JLabel();
private final JLabel icon = new JLabel( UIManager.getIcon( "FileView.floppyDriveIcon" ) );

TestWideTreeCellRenderer() {
super( new BorderLayout() );
setOpaque( false );
add( label, BorderLayout.CENTER );
add( icon, BorderLayout.LINE_END );
setBorder( new LineBorder( Color.red ) );
}

@Override
public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus )
{
label.setText( String.valueOf( value ) );
return this;
}
}

//---- class TestComboBoxTableCellRenderer --------------------------------

private static class TestComboBoxTableCellRenderer
Expand Down
Loading
Loading