mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-07 06:20:53 +03:00
List: support rounded selection for layout orientations VERTICAL_WRAP and HORIZONTAL_WRAP
This commit is contained in:
@@ -22,6 +22,7 @@ import java.awt.EventQueue;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
@@ -185,8 +186,8 @@ public class FlatListUI
|
|||||||
return e -> {
|
return e -> {
|
||||||
superListener.valueChanged( e );
|
superListener.valueChanged( e );
|
||||||
|
|
||||||
// for united rounded selection, repaint parts of the rows that adjoin to the changed rows
|
// for united rounded selection, repaint parts of the rows/columns that adjoin to the changed rows/columns
|
||||||
if( useUnitedRoundedSelection() &&
|
if( useUnitedRoundedSelection( true, true ) &&
|
||||||
!list.isSelectionEmpty() &&
|
!list.isSelectionEmpty() &&
|
||||||
(list.getMaxSelectionIndex() - list.getMinSelectionIndex()) >= 1 )
|
(list.getMaxSelectionIndex() - list.getMinSelectionIndex()) >= 1 )
|
||||||
{
|
{
|
||||||
@@ -196,7 +197,7 @@ public class FlatListUI
|
|||||||
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
||||||
if( r != null ) {
|
if( r != null ) {
|
||||||
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||||
list.repaint( r.x, r.y - arc, r.width, r.height + (arc * 2) );
|
list.repaint( r.x - arc, r.y - arc, r.width + (arc * 2), r.height + (arc * 2) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -359,23 +360,64 @@ public class FlatListUI
|
|||||||
|
|
||||||
/** @since 3 */
|
/** @since 3 */
|
||||||
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
||||||
float arcTop, arcBottom;
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
arcTop = arcBottom = UIScale.scale( selectionArc / 2f );
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
if( useUnitedRoundedSelection() ) {
|
if( list.getLayoutOrientation() == JList.VERTICAL ) {
|
||||||
|
// layout orientation: VERTICAL
|
||||||
|
if( useUnitedRoundedSelection( true, false ) ) {
|
||||||
if( row > 0 && list.isSelectedIndex( row - 1 ) )
|
if( row > 0 && list.isSelectedIndex( row - 1 ) )
|
||||||
arcTop = 0;
|
arcTopLeft = arcTopRight = 0;
|
||||||
if( row < list.getModel().getSize() - 1 && list.isSelectedIndex( row + 1 ) )
|
if( row < list.getModel().getSize() - 1 && list.isSelectedIndex( row + 1 ) )
|
||||||
arcBottom = 0;
|
arcBottomLeft = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// layout orientation: VERTICAL_WRAP or HORIZONTAL_WRAP
|
||||||
|
Rectangle r = null;
|
||||||
|
if( useUnitedRoundedSelection( true, false ) ) {
|
||||||
|
// vertical: check whether cells above or below are selected
|
||||||
|
r = getCellBounds( list, row, row );
|
||||||
|
|
||||||
|
int topIndex = locationToIndex( list, new Point( r.x, r.y - 1 ) );
|
||||||
|
int bottomIndex = locationToIndex( list, new Point( r.x, r.y + r.height ) );
|
||||||
|
|
||||||
|
if( topIndex >= 0 && topIndex != row && list.isSelectedIndex( topIndex ) )
|
||||||
|
arcTopLeft = arcTopRight = 0;
|
||||||
|
if( bottomIndex >= 0 && bottomIndex != row && list.isSelectedIndex( bottomIndex ) )
|
||||||
|
arcBottomLeft = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( useUnitedRoundedSelection( false, true ) ) {
|
||||||
|
// horizontal: check whether cells left or right are selected
|
||||||
|
if( r == null )
|
||||||
|
r = getCellBounds( list, row, row );
|
||||||
|
|
||||||
|
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
||||||
|
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
||||||
|
|
||||||
|
// special handling for the case that last column contains less cells than the other columns
|
||||||
|
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
||||||
|
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
||||||
|
leftIndex = -1;
|
||||||
|
if( ltr && rightIndex >= 0 && rightIndex != row && rightIndex == locationToIndex( list, new Point( r.x + r.width, r.y - 1 ) ) )
|
||||||
|
rightIndex = -1;
|
||||||
|
|
||||||
|
if( leftIndex >= 0 && leftIndex != row && list.isSelectedIndex( leftIndex ) )
|
||||||
|
arcTopLeft = arcBottomLeft = 0;
|
||||||
|
if( rightIndex >= 0 && rightIndex != row && list.isSelectedIndex( rightIndex ) )
|
||||||
|
arcTopRight = arcBottomRight = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||||
UIScale.scale( selectionInsets ), arcTop, arcTop, arcBottom, arcBottom, 0 );
|
UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean useUnitedRoundedSelection() {
|
private boolean useUnitedRoundedSelection( boolean vertical, boolean horizontal ) {
|
||||||
return selectionArc > 0 &&
|
return selectionArc > 0 &&
|
||||||
(selectionInsets == null || (selectionInsets.top == 0 && selectionInsets.bottom == 0));
|
(selectionInsets == null ||
|
||||||
|
(vertical && selectionInsets.top == 0 && selectionInsets.bottom == 0) ||
|
||||||
|
(horizontal && selectionInsets.left == 0 && selectionInsets.right == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Component;
|
|||||||
import java.awt.ComponentOrientation;
|
import java.awt.ComponentOrientation;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
@@ -44,6 +45,8 @@ import javax.swing.tree.TreePath;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.icons.FlatMenuArrowIcon;
|
import com.formdev.flatlaf.icons.FlatMenuArrowIcon;
|
||||||
|
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatListUI;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
import com.jidesoft.swing.*;
|
import com.jidesoft.swing.*;
|
||||||
import com.jidesoft.swing.CheckBoxTreeCellRenderer;
|
import com.jidesoft.swing.CheckBoxTreeCellRenderer;
|
||||||
@@ -361,7 +364,38 @@ public class FlatComponents2Test
|
|||||||
for( JList<String> list : allLists )
|
for( JList<String> list : allLists )
|
||||||
list.setCellRenderer( new TestLabelListCellRenderer() );
|
list.setCellRenderer( new TestLabelListCellRenderer() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "labelRounded":
|
||||||
|
for( JList<String> list : allLists )
|
||||||
|
list.setCellRenderer( new TestLabelRoundedListCellRenderer() );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String style = sel.equals( "labelRounded" )
|
||||||
|
? "selectionArc: 6; selectionInsets: 0,1,0,1"
|
||||||
|
: null;
|
||||||
|
for( JList<String> list : allLists )
|
||||||
|
list.putClientProperty( FlatClientProperties.STYLE, style );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listLayoutOrientationChanged() {
|
||||||
|
int layoutOrientation = JList.VERTICAL;
|
||||||
|
Object sel = listLayoutOrientationField.getSelectedItem();
|
||||||
|
if( sel instanceof String ) {
|
||||||
|
switch( (String) sel ) {
|
||||||
|
case "vertical": layoutOrientation = JList.VERTICAL; break;
|
||||||
|
case "vertical wrap": layoutOrientation = JList.VERTICAL_WRAP; break;
|
||||||
|
case "horzontal wrap": layoutOrientation = JList.HORIZONTAL_WRAP; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( JList<?> list : allLists )
|
||||||
|
list.setLayoutOrientation( layoutOrientation );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listVisibleRowCountChanged() {
|
||||||
|
int visibleRowCount = (Integer) listVisibleRowCountSpinner.getValue();
|
||||||
|
for( JList<?> list : allLists )
|
||||||
|
list.setVisibleRowCount( visibleRowCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void treeRendererChanged() {
|
private void treeRendererChanged() {
|
||||||
@@ -508,6 +542,10 @@ public class FlatComponents2Test
|
|||||||
JPanel panel6 = new JPanel();
|
JPanel panel6 = new JPanel();
|
||||||
JLabel listRendererLabel = new JLabel();
|
JLabel listRendererLabel = new JLabel();
|
||||||
listRendererComboBox = new JComboBox<>();
|
listRendererComboBox = new JComboBox<>();
|
||||||
|
JLabel listLayoutOrientationLabel = new JLabel();
|
||||||
|
listLayoutOrientationField = new JComboBox<>();
|
||||||
|
JLabel listVisibleRowCountLabel = new JLabel();
|
||||||
|
listVisibleRowCountSpinner = new JSpinner();
|
||||||
JPanel treeOptionsPanel = new JPanel();
|
JPanel treeOptionsPanel = new JPanel();
|
||||||
JLabel treeRendererLabel = new JLabel();
|
JLabel treeRendererLabel = new JLabel();
|
||||||
treeRendererComboBox = new JComboBox<>();
|
treeRendererComboBox = new JComboBox<>();
|
||||||
@@ -795,6 +833,8 @@ public class FlatComponents2Test
|
|||||||
"[fill]" +
|
"[fill]" +
|
||||||
"[fill]",
|
"[fill]",
|
||||||
// rows
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
"[]"));
|
"[]"));
|
||||||
|
|
||||||
//---- listRendererLabel ----
|
//---- listRendererLabel ----
|
||||||
@@ -805,10 +845,33 @@ public class FlatComponents2Test
|
|||||||
listRendererComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
|
listRendererComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||||
"default",
|
"default",
|
||||||
"defaultSubclass",
|
"defaultSubclass",
|
||||||
"label"
|
"label",
|
||||||
|
"labelRounded"
|
||||||
}));
|
}));
|
||||||
listRendererComboBox.addActionListener(e -> listRendererChanged());
|
listRendererComboBox.addActionListener(e -> listRendererChanged());
|
||||||
panel6.add(listRendererComboBox, "cell 1 0");
|
panel6.add(listRendererComboBox, "cell 1 0");
|
||||||
|
|
||||||
|
//---- listLayoutOrientationLabel ----
|
||||||
|
listLayoutOrientationLabel.setText("Orientation:");
|
||||||
|
panel6.add(listLayoutOrientationLabel, "cell 0 1");
|
||||||
|
|
||||||
|
//---- listLayoutOrientationField ----
|
||||||
|
listLayoutOrientationField.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||||
|
"vertical",
|
||||||
|
"vertical wrap",
|
||||||
|
"horzontal wrap"
|
||||||
|
}));
|
||||||
|
listLayoutOrientationField.addActionListener(e -> listLayoutOrientationChanged());
|
||||||
|
panel6.add(listLayoutOrientationField, "cell 1 1");
|
||||||
|
|
||||||
|
//---- listVisibleRowCountLabel ----
|
||||||
|
listVisibleRowCountLabel.setText("Visible row count:");
|
||||||
|
panel6.add(listVisibleRowCountLabel, "cell 0 2");
|
||||||
|
|
||||||
|
//---- listVisibleRowCountSpinner ----
|
||||||
|
listVisibleRowCountSpinner.setModel(new SpinnerNumberModel(8, 0, null, 1));
|
||||||
|
listVisibleRowCountSpinner.addChangeListener(e -> listVisibleRowCountChanged());
|
||||||
|
panel6.add(listVisibleRowCountSpinner, "cell 1 2");
|
||||||
}
|
}
|
||||||
add(panel6, "cell 0 4 4 1");
|
add(panel6, "cell 0 4 4 1");
|
||||||
|
|
||||||
@@ -973,6 +1036,8 @@ public class FlatComponents2Test
|
|||||||
private JXTreeTable xTreeTable1;
|
private JXTreeTable xTreeTable1;
|
||||||
private JCheckBox dndCheckBox;
|
private JCheckBox dndCheckBox;
|
||||||
private JComboBox<String> listRendererComboBox;
|
private JComboBox<String> listRendererComboBox;
|
||||||
|
private JComboBox<String> listLayoutOrientationField;
|
||||||
|
private JSpinner listVisibleRowCountSpinner;
|
||||||
private JComboBox<String> treeRendererComboBox;
|
private JComboBox<String> treeRendererComboBox;
|
||||||
private JCheckBox treeWideSelectionCheckBox;
|
private JCheckBox treeWideSelectionCheckBox;
|
||||||
private JCheckBox treePaintSelectionCheckBox;
|
private JCheckBox treePaintSelectionCheckBox;
|
||||||
@@ -1371,6 +1436,45 @@ public class FlatComponents2Test
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class TestLabelRoundedListCellRenderer -----------------------------
|
||||||
|
|
||||||
|
private static class TestLabelRoundedListCellRenderer
|
||||||
|
extends JLabel
|
||||||
|
implements ListCellRenderer<String>
|
||||||
|
{
|
||||||
|
private JList<? extends String> list;
|
||||||
|
private int index;
|
||||||
|
private boolean isSelected;
|
||||||
|
|
||||||
|
TestLabelRoundedListCellRenderer() {
|
||||||
|
setBorder( new FlatEmptyBorder( 1, 6, 1, 6 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent( JList<? extends String> list,
|
||||||
|
String value, int index, boolean isSelected, boolean cellHasFocus )
|
||||||
|
{
|
||||||
|
this.list = list;
|
||||||
|
this.index = index;
|
||||||
|
this.isSelected = isSelected;
|
||||||
|
|
||||||
|
setText( String.valueOf( value ) );
|
||||||
|
setBackground( isSelected ? Color.green : list.getBackground() );
|
||||||
|
setForeground( isSelected ? Color.blue : list.getForeground() );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent( Graphics g ) {
|
||||||
|
if( isSelected ) {
|
||||||
|
g.setColor( getBackground() );
|
||||||
|
FlatListUI.paintCellSelection( list, g, index, 0, 0, getWidth(), getHeight() );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintComponent( g );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- class TestDefaultTreeCellRenderer ----------------------------------
|
//---- class TestDefaultTreeCellRenderer ----------------------------------
|
||||||
|
|
||||||
private static class TestDefaultTreeCellRenderer
|
private static class TestDefaultTreeCellRenderer
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ new FormModel {
|
|||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
"$layoutConstraints": "hidemode 3"
|
"$layoutConstraints": "hidemode 3"
|
||||||
"$columnConstraints": "[fill][fill]"
|
"$columnConstraints": "[fill][fill]"
|
||||||
"$rowConstraints": "[]"
|
"$rowConstraints": "[][][]"
|
||||||
} ) {
|
} ) {
|
||||||
name: "panel6"
|
name: "panel6"
|
||||||
"border": new javax.swing.border.TitledBorder( "JList Control" )
|
"border": new javax.swing.border.TitledBorder( "JList Control" )
|
||||||
@@ -335,6 +335,7 @@ new FormModel {
|
|||||||
addElement( "default" )
|
addElement( "default" )
|
||||||
addElement( "defaultSubclass" )
|
addElement( "defaultSubclass" )
|
||||||
addElement( "label" )
|
addElement( "label" )
|
||||||
|
addElement( "labelRounded" )
|
||||||
}
|
}
|
||||||
auxiliary() {
|
auxiliary() {
|
||||||
"JavaCodeGenerator.variableLocal": false
|
"JavaCodeGenerator.variableLocal": false
|
||||||
@@ -343,6 +344,47 @@ new FormModel {
|
|||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 1 0"
|
"value": "cell 1 0"
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "listLayoutOrientationLabel"
|
||||||
|
"text": "Orientation:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "listLayoutOrientationField"
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "vertical"
|
||||||
|
addElement( "vertical" )
|
||||||
|
addElement( "vertical wrap" )
|
||||||
|
addElement( "horzontal wrap" )
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
"JavaCodeGenerator.typeParameters": "String"
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listLayoutOrientationChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "listVisibleRowCountLabel"
|
||||||
|
"text": "Visible row count:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSpinner" ) {
|
||||||
|
name: "listVisibleRowCountSpinner"
|
||||||
|
"model": new javax.swing.SpinnerNumberModel {
|
||||||
|
minimum: 0
|
||||||
|
value: 8
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "listVisibleRowCountChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 0 4 4 1"
|
"value": "cell 0 4 4 1"
|
||||||
} )
|
} )
|
||||||
|
|||||||
Reference in New Issue
Block a user