ComboBox (not editable):

- increased size of internal renderer pane to the component border so that it can paint within the whole component
- increase combo box size if a custom renderer uses a border with insets that are larger than the default combo box padding (`2,6,2,6`)
This commit is contained in:
Karl Tauber
2021-07-05 18:41:17 +02:00
parent b576f473e5
commit a22c6c8013
4 changed files with 56 additions and 59 deletions

View File

@@ -18,6 +18,10 @@ FlatLaf Change Log
of text now positions caret to first character instead of opening ComboBox of text now positions caret to first character instead of opening ComboBox
popup; mouse cursor is now of type "text" within the whole component, except popup; mouse cursor is now of type "text" within the whole component, except
for arrow buttons). (issue #330) for arrow buttons). (issue #330)
- ComboBox (not editable): Increased size of internal renderer pane to the
component border so that it can paint within the whole component. Also
increase combo box size if a custom renderer uses a border with insets that
are larger than the default combo box padding (`2,6,2,6`).
- Fixed component heights at `1.25x`, `1.75x` and `2.25x` scaling factors (Java - Fixed component heights at `1.25x`, `1.75x` and `2.25x` scaling factors (Java
8 only) so that Button, ComboBox, Spinner and TextField components (including 8 only) so that Button, ComboBox, Spinner and TextField components (including
subclasses) have same heights. This increases heights of Button and TextField subclasses) have same heights. This increases heights of Button and TextField

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import static com.formdev.flatlaf.util.UIScale.unscale;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.ComponentOrientation; import java.awt.ComponentOrientation;
@@ -67,7 +68,6 @@ import javax.swing.plaf.basic.ComboPopup;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
/** /**
* Provides the Flat LaF UI delegate for {@link javax.swing.JComboBox}. * Provides the Flat LaF UI delegate for {@link javax.swing.JComboBox}.
@@ -132,8 +132,6 @@ public class FlatComboBoxUI
protected Color popupBackground; protected Color popupBackground;
protected Insets paddingUnscaled;
private MouseListener hoverListener; private MouseListener hoverListener;
protected boolean hover; protected boolean hover;
protected boolean pressed; protected boolean pressed;
@@ -223,10 +221,6 @@ public class FlatComboBoxUI
if( maximumRowCount > 0 && maximumRowCount != 8 && comboBox.getMaximumRowCount() == 8 ) if( maximumRowCount > 0 && maximumRowCount != 8 && comboBox.getMaximumRowCount() == 8 )
comboBox.setMaximumRowCount( maximumRowCount ); comboBox.setMaximumRowCount( maximumRowCount );
// scale
paddingUnscaled = padding;
padding = UIScale.scale( paddingUnscaled );
paddingBorder = new CellPaddingBorder( padding ); paddingBorder = new CellPaddingBorder( padding );
MigLayoutVisualPadding.install( comboBox ); MigLayoutVisualPadding.install( comboBox );
@@ -368,9 +362,6 @@ public class FlatComboBoxUI
// remove default text field border from editor // remove default text field border from editor
if( textField.getBorder() instanceof FlatTextBorder ) if( textField.getBorder() instanceof FlatTextBorder )
textField.setBorder( BorderFactory.createEmptyBorder() ); textField.setBorder( BorderFactory.createEmptyBorder() );
// editor padding
textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, paddingUnscaled );
} }
// explicitly make non-opaque // explicitly make non-opaque
@@ -379,6 +370,7 @@ public class FlatComboBoxUI
editor.applyComponentOrientation( comboBox.getComponentOrientation() ); editor.applyComponentOrientation( comboBox.getComponentOrientation() );
updateEditorPadding();
updateEditorColors(); updateEditorColors();
// macOS // macOS
@@ -395,6 +387,25 @@ public class FlatComboBoxUI
} }
} }
private void updateEditorPadding() {
if( !(editor instanceof JTextField) )
return;
JTextField textField = (JTextField) editor;
Insets insets = textField.getInsets();
Insets pad = padding;
if( insets.top != 0 || insets.left != 0 || insets.bottom != 0 || insets.right != 0 ) {
// if text field has custom border, subtract text field insets from padding
pad = new Insets(
unscale( Math.max( scale( padding.top ) - insets.top, 0 ) ),
unscale( Math.max( scale( padding.left ) - insets.left, 0 ) ),
unscale( Math.max( scale( padding.bottom ) - insets.bottom, 0 ) ),
unscale( Math.max( scale( padding.right ) - insets.right, 0 ) )
);
}
textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, pad );
}
private void updateEditorColors() { private void updateEditorColors() {
// use non-UIResource colors because when SwingUtilities.updateComponentTreeUI() // use non-UIResource colors because when SwingUtilities.updateComponentTreeUI()
// is used, then the editor is updated after the combobox and the // is used, then the editor is updated after the combobox and the
@@ -493,16 +504,10 @@ public class FlatComboBoxUI
c.setForeground( getForeground( enabled ) ); c.setForeground( getForeground( enabled ) );
boolean shouldValidate = (c instanceof JPanel); boolean shouldValidate = (c instanceof JPanel);
if( padding != null )
bounds = FlatUIUtils.subtractInsets( bounds, padding );
// increase the size of the rendering area to make sure that the text
// is vertically aligned with other component types (e.g. JTextField)
Insets rendererInsets = getRendererComponentInsets( c );
if( rendererInsets != null )
bounds = FlatUIUtils.addInsets( bounds, rendererInsets );
paddingBorder.install( c );
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate ); currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
paddingBorder.uninstall();
} }
@Override @Override
@@ -549,51 +554,35 @@ public class FlatComboBoxUI
@Override @Override
protected Dimension getDisplaySize() { protected Dimension getDisplaySize() {
// update padding
padding = UIScale.scale( paddingUnscaled );
paddingBorder.uninstall(); paddingBorder.uninstall();
Dimension displaySize = super.getDisplaySize(); Dimension displaySize = super.getDisplaySize();
paddingBorder.uninstall(); paddingBorder.uninstall();
// remove padding added in super.getDisplaySize()
int displayWidth = displaySize.width - padding.left - padding.right;
int displayHeight = displaySize.height - padding.top - padding.bottom;
// recalculate width without hardcoded 100 under special conditions // recalculate width without hardcoded 100 under special conditions
if( displaySize.width == 100 + padding.left + padding.right && if( displayWidth == 100 &&
comboBox.isEditable() && comboBox.isEditable() &&
comboBox.getItemCount() == 0 && comboBox.getItemCount() == 0 &&
comboBox.getPrototypeDisplayValue() == null ) comboBox.getPrototypeDisplayValue() == null )
{ {
int width = getDefaultSize().width; displayWidth = Math.max( getDefaultSize().width, editor.getPreferredSize().width );
width = Math.max( width, editor.getPreferredSize().width );
width += padding.left + padding.right;
displaySize = new Dimension( width, displaySize.height );
} }
return displaySize; return new Dimension( displayWidth, displayHeight );
} }
@Override @Override
protected Dimension getSizeForComponent( Component comp ) { protected Dimension getSizeForComponent( Component comp ) {
paddingBorder.install( comp );
Dimension size = super.getSizeForComponent( comp ); Dimension size = super.getSizeForComponent( comp );
paddingBorder.uninstall();
// remove the renderer border top/bottom insets from the size to make sure that
// the combobox gets the same height as other component types (e.g. JTextField)
Insets rendererInsets = getRendererComponentInsets( comp );
if( rendererInsets != null )
size = new Dimension( size.width, size.height - rendererInsets.top - rendererInsets.bottom );
return size; return size;
} }
private Insets getRendererComponentInsets( Component rendererComponent ) {
if( rendererComponent instanceof JComponent ) {
Border rendererBorder = ((JComponent)rendererComponent).getBorder();
if( rendererBorder != null )
return rendererBorder.getBorderInsets( rendererComponent );
}
return null;
}
private boolean isCellRenderer() { private boolean isCellRenderer() {
return comboBox.getParent() instanceof CellRendererPane; return comboBox.getParent() instanceof CellRendererPane;
} }
@@ -661,7 +650,7 @@ public class FlatComboBoxUI
super( combo ); super( combo );
// BasicComboPopup listens to JComboBox.componentOrientation and updates // BasicComboPopup listens to JComboBox.componentOrientation and updates
// the component orientation of the list, scroller and popup, but when // the component orientation of the list, scroll pane and popup, but when
// switching the LaF and a new combo popup is created, the component // switching the LaF and a new combo popup is created, the component
// orientation is not applied. // orientation is not applied.
ComponentOrientation o = comboBox.getComponentOrientation(); ComponentOrientation o = comboBox.getComponentOrientation();
@@ -780,7 +769,7 @@ public class FlatComboBoxUI
//---- class CellPaddingBorder -------------------------------------------- //---- class CellPaddingBorder --------------------------------------------
/** /**
* Cell padding border used only in popup list. * Cell padding border used in popup list and for current value if not editable.
* <p> * <p>
* The insets are the union of the cell padding and the renderer border insets, * The insets are the union of the cell padding and the renderer border insets,
* which vertically aligns text in popup list with text in combobox. * which vertically aligns text in popup list with text in combobox.
@@ -836,6 +825,7 @@ public class FlatComboBoxUI
@Override @Override
public Insets getBorderInsets( Component c, Insets insets ) { public Insets getBorderInsets( Component c, Insets insets ) {
Insets padding = scale( this.padding );
if( rendererBorder != null ) { if( rendererBorder != null ) {
Insets insideInsets = rendererBorder.getBorderInsets( c ); Insets insideInsets = rendererBorder.getBorderInsets( c );
insets.top = Math.max( padding.top, insideInsets.top ); insets.top = Math.max( padding.top, insideInsets.top );

View File

@@ -114,17 +114,19 @@ public class TestFlatComponentSizes
void comboBox( float factor ) { void comboBox( float factor ) {
TestUtils.scaleFont( factor ); TestUtils.scaleFont( factor );
JComboBox<String> comboBox = new JComboBox<>(); String[] items = { "text" };
JComboBox<String> comboBox2 = new JComboBox<>(); JComboBox<String> comboBox = new JComboBox<>( items );
JComboBox<String> comboBox3 = new JComboBox<>(); JComboBox<String> comboBox2 = new JComboBox<>( items );
JComboBox<String> comboBox4 = new JComboBox<>(); JComboBox<String> comboBox3 = new JComboBox<>( items );
JComboBox<String> comboBox4 = new JComboBox<>( items );
applyCustomComboBoxRendererBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 3 ) ) ); applyCustomComboBoxRendererBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 6 ) ) );
applyCustomComboBoxRendererBorder( comboBox3, new BorderWithIcon() ); applyCustomComboBoxRendererBorder( comboBox3, new BorderWithIcon() );
applyCustomComboBoxRendererBorder( comboBox4, null ); applyCustomComboBoxRendererBorder( comboBox4, null );
Dimension size = comboBox.getPreferredSize(); Dimension size = comboBox.getPreferredSize();
assertEquals( size, comboBox2.getPreferredSize() ); assertEquals( size.width, comboBox2.getPreferredSize().width );
assertEquals( size.height - (2 * UIScale.scale( 2 )) + (2 * UIScale.scale( 6 )), comboBox2.getPreferredSize().height );
assertEquals( size, comboBox3.getPreferredSize() ); assertEquals( size, comboBox3.getPreferredSize() );
assertEquals( size, comboBox4.getPreferredSize() ); assertEquals( size, comboBox4.getPreferredSize() );
@@ -143,23 +145,24 @@ public class TestFlatComponentSizes
void comboBoxEditable( float factor ) { void comboBoxEditable( float factor ) {
TestUtils.scaleFont( factor ); TestUtils.scaleFont( factor );
JComboBox<String> comboBox = new JComboBox<>(); String[] items = { "text" };
JComboBox<String> comboBox2 = new JComboBox<>(); JComboBox<String> comboBox = new JComboBox<>( items );
JComboBox<String> comboBox3 = new JComboBox<>(); JComboBox<String> comboBox2 = new JComboBox<>( items );
JComboBox<String> comboBox4 = new JComboBox<>(); JComboBox<String> comboBox3 = new JComboBox<>( items );
JComboBox<String> comboBox4 = new JComboBox<>( items );
comboBox.setEditable( true ); comboBox.setEditable( true );
comboBox2.setEditable( true ); comboBox2.setEditable( true );
comboBox3.setEditable( true ); comboBox3.setEditable( true );
comboBox4.setEditable( true ); comboBox4.setEditable( true );
applyCustomComboBoxEditorBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 3 ) ) ); applyCustomComboBoxEditorBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 6 ) ) );
applyCustomComboBoxEditorBorder( comboBox3, new BorderWithIcon() ); applyCustomComboBoxEditorBorder( comboBox3, new BorderWithIcon() );
applyCustomComboBoxEditorBorder( comboBox4, null ); applyCustomComboBoxEditorBorder( comboBox4, null );
Dimension size = comboBox.getPreferredSize(); Dimension size = comboBox.getPreferredSize();
assertEquals( size.width, comboBox2.getPreferredSize().width ); assertEquals( size.width, comboBox2.getPreferredSize().width );
assertEquals( size.height + (2 * UIScale.scale( 3 )), comboBox2.getPreferredSize().height ); assertEquals( size.height - (2 * UIScale.scale( 2 )) + (2 * UIScale.scale( 6 )), comboBox2.getPreferredSize().height );
assertEquals( size, comboBox3.getPreferredSize() ); assertEquals( size, comboBox3.getPreferredSize() );
assertEquals( size, comboBox4.getPreferredSize() ); assertEquals( size, comboBox4.getPreferredSize() );

View File

@@ -132,7 +132,7 @@ public class FlatCustomBordersTest
} }
private void applyCustomComboBoxEditorBorder( JComboBox<String> comboBox ) { private void applyCustomComboBoxEditorBorder( JComboBox<String> comboBox ) {
applyCustomComboBoxEditorBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 3 ) ) ); applyCustomComboBoxEditorBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
} }
private void applyCustomComboBoxEditorBorderWithIcon( JComboBox<String> comboBox ) { private void applyCustomComboBoxEditorBorderWithIcon( JComboBox<String> comboBox ) {
@@ -152,7 +152,7 @@ public class FlatCustomBordersTest
} }
private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox ) { private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox ) {
applyCustomComboBoxRendererBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 3 ) ) ); applyCustomComboBoxRendererBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
} }
private void applyCustomComboBoxRendererBorderWithIcon( JComboBox<String> comboBox ) { private void applyCustomComboBoxRendererBorderWithIcon( JComboBox<String> comboBox ) {