ComboBox: fixed StackOverflowError when using single renderer instance in multiple comboboxes (regression since commit 4507ce359d)

This commit is contained in:
Karl Tauber
2021-07-09 11:39:35 +02:00
parent ff9ef21f67
commit 1de81d0af5
3 changed files with 95 additions and 2 deletions

View File

@@ -791,14 +791,20 @@ public class FlatComboBoxUI
if( oldBorder == this )
return; // already installed
// component already has a padding border --> uninstall it
// (may happen if single renderer instance is used in multiple comboboxes)
if( oldBorder instanceof CellPaddingBorder )
((CellPaddingBorder)oldBorder).uninstall();
// this border can be installed only at one component
// (may happen if a renderer returns varying components)
uninstall();
// remember component where this border was installed for uninstall
rendererComponent = jc;
// remember old border and replace it
rendererBorder = oldBorder;
rendererBorder = jc.getBorder();
rendererComponent.setBorder( this );
}

View File

@@ -47,6 +47,7 @@ public class FlatCustomBordersTest
FlatCustomBordersTest() {
initComponents();
applyCustomBorders();
applySpecialComboBoxRenderers();
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>( new String[] {
"text",
@@ -123,6 +124,33 @@ public class FlatCustomBordersTest
applyCustomComboBoxRendererBorder( comboBox28, null );
}
@SuppressWarnings( "unchecked" )
private void applySpecialComboBoxRenderers() {
BasicComboBoxRenderer sharedRenderer = new BasicComboBoxRenderer();
sharedRenderer.setBorder( new LineBorder( ORANGE, UIScale.scale( 2 ) ) );
comboBox29.setRenderer( sharedRenderer );
comboBox30.setRenderer( sharedRenderer );
comboBox31.setRenderer( new ListCellRenderer<String>() {
JLabel l1 = new JLabel();
JLabel l2 = new JLabel();
@Override
public Component getListCellRendererComponent( JList<? extends String> list,
String value, int index, boolean isSelected, boolean cellHasFocus )
{
JLabel l = (index % 2 == 0) ? l1 : l2;
l.setText( (value != null) ? value.toString() : "" );
l.setBorder( new LineBorder( (index % 2 == 0) ? GREEN : RED, UIScale.scale( 2 ) ) );
l.setBackground( isSelected ? list.getSelectionBackground() : list.getBackground() );
l.setForeground( isSelected ? list.getSelectionForeground() : list.getForeground() );
l.setFont( list.getFont() );
l.setOpaque( true );
return l;
}
} );
}
private void applyCustomInsideBorder( JComponent c, String uiKey ) {
c.setBorder( new CompoundBorder( UIManager.getBorder( uiKey ), new LineBorder( RED, UIScale.scale( 3 ) ) ) );
}
@@ -231,6 +259,11 @@ public class FlatCustomBordersTest
textField6 = new JTextField();
textField7 = new JTextField();
textField8 = new JTextField();
label11 = new JLabel();
label12 = new JLabel();
comboBox29 = new JComboBox<>();
comboBox30 = new JComboBox<>();
comboBox31 = new JComboBox<>();
//======== this ========
setLayout(new MigLayout(
@@ -255,6 +288,8 @@ public class FlatCustomBordersTest
"[]" +
"[]" +
"[]" +
"[]para" +
"[]" +
"[]"));
//---- label1 ----
@@ -493,6 +528,17 @@ public class FlatCustomBordersTest
textField8.putClientProperty("JComponent.roundRect", true);
textField8.setText("text");
add(textField8, "cell 4 10");
//---- label11 ----
label11.setText("JComboBox with shared renderer:");
add(label11, "cell 1 11 2 1");
//---- label12 ----
label12.setText("JComboBox with renderer that uses varying components:");
add(label12, "cell 3 11 3 1");
add(comboBox29, "cell 1 12");
add(comboBox30, "cell 2 12");
add(comboBox31, "cell 3 12");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
@@ -560,6 +606,11 @@ public class FlatCustomBordersTest
private JTextField textField6;
private JTextField textField7;
private JTextField textField8;
private JLabel label11;
private JLabel label12;
private JComboBox<String> comboBox29;
private JComboBox<String> comboBox30;
private JComboBox<String> comboBox31;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class BorderWithIcon -----------------------------------------------

View File

@@ -6,7 +6,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][fill][fill][fill][fill][fill][fill][fill]"
"$rowConstraints": "[][][][][][][][][][][]"
"$rowConstraints": "[][][][][][][][][][][]para[][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -478,6 +478,42 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 10"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label11"
"text": "JComboBox with shared renderer:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 11 2 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label12"
"text": "JComboBox with renderer that uses varying components:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 11 3 1"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox29"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 12"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox30"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 12"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox31"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 12"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 915, 715 )