ComboBox (editable) and Spinner: increased size of internal text field to the component border so that it behaves like plain text field (issue #330)

This commit is contained in:
Karl Tauber
2021-07-02 18:43:37 +02:00
parent a9dcf09d13
commit 3e14f28dc2
5 changed files with 153 additions and 16 deletions

View File

@@ -13,7 +13,11 @@ FlatLaf Change Log
#### Fixed bugs #### Fixed bugs
- TBD - ComboBox (editable) and Spinner: Increased size of internal text field to the
component border so that it behaves like plain text field (mouse click to left
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
for arrow buttons). (issue #330)
## 1.3 ## 1.3

View File

@@ -133,6 +133,8 @@ 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,7 +225,8 @@ public class FlatComboBoxUI
comboBox.setMaximumRowCount( maximumRowCount ); comboBox.setMaximumRowCount( maximumRowCount );
// scale // scale
padding = UIScale.scale( padding ); paddingUnscaled = padding;
padding = UIScale.scale( paddingUnscaled );
MigLayoutVisualPadding.install( comboBox ); MigLayoutVisualPadding.install( comboBox );
} }
@@ -276,11 +279,6 @@ public class FlatComboBoxUI
editor.setBounds( rectangleForCurrentValue() ); editor.setBounds( rectangleForCurrentValue() );
} }
} }
if( editor != null && padding != null ) {
// fix editor bounds by subtracting padding
editor.setBounds( FlatUIUtils.subtractInsets( editor.getBounds(), padding ) );
}
} }
}; };
} }
@@ -361,9 +359,16 @@ public class FlatComboBoxUI
protected void configureEditor() { protected void configureEditor() {
super.configureEditor(); super.configureEditor();
// remove default text field border from editor if( editor instanceof JTextField ) {
if( editor instanceof JTextField && ((JTextField)editor).getBorder() instanceof FlatTextBorder ) JTextField textField = (JTextField) editor;
((JTextField)editor).setBorder( BorderFactory.createEmptyBorder() );
// remove default text field border from editor
if( textField.getBorder() instanceof FlatTextBorder )
textField.setBorder( BorderFactory.createEmptyBorder() );
// editor padding
textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, paddingUnscaled );
}
// explicitly make non-opaque // explicitly make non-opaque
if( editor instanceof JComponent ) if( editor instanceof JComponent )
@@ -548,6 +553,9 @@ public class FlatComboBoxUI
ListCellRenderer<Object> renderer = comboBox.getRenderer(); ListCellRenderer<Object> renderer = comboBox.getRenderer();
uninstallCellPaddingBorder( renderer ); uninstallCellPaddingBorder( renderer );
// update padding
padding = UIScale.scale( paddingUnscaled );
Dimension displaySize = super.getDisplaySize(); Dimension displaySize = super.getDisplaySize();
// recalculate width without hardcoded 100 under special conditions // recalculate width without hardcoded 100 under special conditions

View File

@@ -123,9 +123,6 @@ public class FlatSpinnerUI
buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" ); buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" );
padding = UIManager.getInsets( "Spinner.padding" ); padding = UIManager.getInsets( "Spinner.padding" );
// scale
padding = scale( padding );
MigLayoutVisualPadding.install( spinner ); MigLayoutVisualPadding.install( spinner );
} }
@@ -184,6 +181,7 @@ public class FlatSpinnerUI
if( textField != null ) if( textField != null )
textField.setOpaque( false ); textField.setOpaque( false );
updateEditorPadding();
updateEditorColors(); updateEditorColors();
return editor; return editor;
} }
@@ -194,6 +192,8 @@ public class FlatSpinnerUI
removeEditorFocusListener( oldEditor ); removeEditorFocusListener( oldEditor );
addEditorFocusListener( newEditor ); addEditorFocusListener( newEditor );
updateEditorPadding();
updateEditorColors(); updateEditorColors();
} }
@@ -209,6 +209,12 @@ public class FlatSpinnerUI
textField.removeFocusListener( getHandler() ); textField.removeFocusListener( getHandler() );
} }
private void updateEditorPadding() {
JTextField textField = getEditorTextField( spinner.getEditor() );
if( textField != null )
textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding );
}
private void updateEditorColors() { private void updateEditorColors() {
JTextField textField = getEditorTextField( spinner.getEditor() ); JTextField textField = getEditorTextField( spinner.getEditor() );
if( textField != null ) { if( textField != null ) {
@@ -373,6 +379,7 @@ public class FlatSpinnerUI
@Override @Override
public Dimension preferredLayoutSize( Container parent ) { public Dimension preferredLayoutSize( Container parent ) {
Insets insets = parent.getInsets(); Insets insets = parent.getInsets();
Insets padding = scale( FlatSpinnerUI.this.padding );
Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 ); Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 );
// the arrows width is the same as the inner height so that the arrows area is square // the arrows width is the same as the inner height so that the arrows area is square
@@ -397,7 +404,7 @@ public class FlatSpinnerUI
if( nextButton == null && previousButton == null ) { if( nextButton == null && previousButton == null ) {
if( editor != null ) if( editor != null )
editor.setBounds( FlatUIUtils.subtractInsets( r, padding ) ); editor.setBounds( r );
return; return;
} }
@@ -417,7 +424,7 @@ public class FlatSpinnerUI
} }
if( editor != null ) if( editor != null )
editor.setBounds( FlatUIUtils.subtractInsets( editorRect, padding ) ); editor.setBounds( editorRect );
int nextHeight = (buttonsRect.height / 2) + (buttonsRect.height % 2); // round up int nextHeight = (buttonsRect.height / 2) + (buttonsRect.height % 2); // round up
if( nextButton != null ) if( nextButton != null )

View File

@@ -20,6 +20,7 @@ import java.awt.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.plaf.basic.BasicComboBoxEditor; import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon; import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
@@ -42,9 +43,23 @@ public class FlatCustomBordersTest
} ); } );
} }
@SuppressWarnings( "unchecked" )
FlatCustomBordersTest() { FlatCustomBordersTest() {
initComponents(); initComponents();
applyCustomBorders(); applyCustomBorders();
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>( new String[] {
"text",
"123",
"4567",
"abc",
"def"
} );
for( Component c : getComponents() ) {
if( c instanceof JComboBox )
((JComboBox<String>)c).setModel( model );
}
} }
@Override @Override
@@ -99,6 +114,13 @@ public class FlatCustomBordersTest
applyCustomComboBoxEditorBorderWithIcon( comboBox20 ); applyCustomComboBoxEditorBorderWithIcon( comboBox20 );
applyCustomComboBoxEditorBorder( comboBox21, null ); applyCustomComboBoxEditorBorder( comboBox21, null );
applyCustomComboBoxEditorBorder( comboBox22, null ); applyCustomComboBoxEditorBorder( comboBox22, null );
applyCustomComboBoxRendererBorder( comboBox23 );
applyCustomComboBoxRendererBorder( comboBox24 );
applyCustomComboBoxRendererBorderWithIcon( comboBox25 );
applyCustomComboBoxRendererBorderWithIcon( comboBox26 );
applyCustomComboBoxRendererBorder( comboBox27, null );
applyCustomComboBoxRendererBorder( comboBox28, null );
} }
private void applyCustomInsideBorder( JComponent c, String uiKey ) { private void applyCustomInsideBorder( JComponent c, String uiKey ) {
@@ -129,6 +151,21 @@ public class FlatCustomBordersTest
} ); } );
} }
private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox ) {
applyCustomComboBoxRendererBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 3 ) ) );
}
private void applyCustomComboBoxRendererBorderWithIcon( JComboBox<String> comboBox ) {
applyCustomComboBoxRendererBorder( comboBox, new BorderWithIcon() );
}
@SuppressWarnings( "unchecked" )
private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox, Border border ) {
BasicComboBoxRenderer customRenderer = new BasicComboBoxRenderer();
customRenderer.setBorder( border );
comboBox.setRenderer( customRenderer );
}
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel(); label1 = new JLabel();
@@ -152,10 +189,16 @@ public class FlatCustomBordersTest
comboBox2 = new JComboBox<>(); comboBox2 = new JComboBox<>();
comboBox3 = new JComboBox<>(); comboBox3 = new JComboBox<>();
comboBox4 = new JComboBox<>(); comboBox4 = new JComboBox<>();
comboBox23 = new JComboBox<>();
comboBox25 = new JComboBox<>();
comboBox27 = new JComboBox<>();
comboBox5 = new JComboBox<>(); comboBox5 = new JComboBox<>();
comboBox6 = new JComboBox<>(); comboBox6 = new JComboBox<>();
comboBox7 = new JComboBox<>(); comboBox7 = new JComboBox<>();
comboBox8 = new JComboBox<>(); comboBox8 = new JComboBox<>();
comboBox24 = new JComboBox<>();
comboBox26 = new JComboBox<>();
comboBox28 = new JComboBox<>();
comboBox9 = new JComboBox<>(); comboBox9 = new JComboBox<>();
comboBox10 = new JComboBox<>(); comboBox10 = new JComboBox<>();
comboBox11 = new JComboBox<>(); comboBox11 = new JComboBox<>();
@@ -289,6 +332,9 @@ public class FlatCustomBordersTest
add(comboBox2, "cell 2 3"); add(comboBox2, "cell 2 3");
add(comboBox3, "cell 3 3"); add(comboBox3, "cell 3 3");
add(comboBox4, "cell 4 3"); add(comboBox4, "cell 4 3");
add(comboBox23, "cell 5 3");
add(comboBox25, "cell 6 3");
add(comboBox27, "cell 7 3");
//---- comboBox5 ---- //---- comboBox5 ----
comboBox5.putClientProperty("JComponent.roundRect", true); comboBox5.putClientProperty("JComponent.roundRect", true);
@@ -306,6 +352,18 @@ public class FlatCustomBordersTest
comboBox8.putClientProperty("JComponent.roundRect", true); comboBox8.putClientProperty("JComponent.roundRect", true);
add(comboBox8, "cell 4 4"); add(comboBox8, "cell 4 4");
//---- comboBox24 ----
comboBox24.putClientProperty("JComponent.roundRect", true);
add(comboBox24, "cell 5 4");
//---- comboBox26 ----
comboBox26.putClientProperty("JComponent.roundRect", true);
add(comboBox26, "cell 6 4");
//---- comboBox28 ----
comboBox28.putClientProperty("JComponent.roundRect", true);
add(comboBox28, "cell 7 4");
//---- comboBox9 ---- //---- comboBox9 ----
comboBox9.setEditable(true); comboBox9.setEditable(true);
add(comboBox9, "cell 1 5"); add(comboBox9, "cell 1 5");
@@ -460,10 +518,16 @@ public class FlatCustomBordersTest
private JComboBox<String> comboBox2; private JComboBox<String> comboBox2;
private JComboBox<String> comboBox3; private JComboBox<String> comboBox3;
private JComboBox<String> comboBox4; private JComboBox<String> comboBox4;
private JComboBox<String> comboBox23;
private JComboBox<String> comboBox25;
private JComboBox<String> comboBox27;
private JComboBox<String> comboBox5; private JComboBox<String> comboBox5;
private JComboBox<String> comboBox6; private JComboBox<String> comboBox6;
private JComboBox<String> comboBox7; private JComboBox<String> comboBox7;
private JComboBox<String> comboBox8; private JComboBox<String> comboBox8;
private JComboBox<String> comboBox24;
private JComboBox<String> comboBox26;
private JComboBox<String> comboBox28;
private JComboBox<String> comboBox9; private JComboBox<String> comboBox9;
private JComboBox<String> comboBox10; private JComboBox<String> comboBox10;
private JComboBox<String> comboBox11; private JComboBox<String> comboBox11;
@@ -508,6 +572,9 @@ public class FlatCustomBordersTest
@Override @Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
icon.paintIcon( c, g, x + width - icon.getIconWidth() - 2, y + ((height - icon.getIconHeight()) / 2) ); icon.paintIcon( c, g, x + width - icon.getIconWidth() - 2, y + ((height - icon.getIconHeight()) / 2) );
g.setColor( RED );
g.drawRect( x, y, width - 1, height - 1 );
} }
@Override @Override

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8" JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -147,6 +147,30 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 3" "value": "cell 4 3"
} ) } )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox23"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 3"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox25"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 6 3"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox27"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 3"
} )
add( new FormComponent( "javax.swing.JComboBox" ) { add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox5" name: "comboBox5"
"$client.JComponent.roundRect": true "$client.JComponent.roundRect": true
@@ -183,6 +207,33 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 4" "value": "cell 4 4"
} ) } )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox24"
"$client.JComponent.roundRect": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 4"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox26"
"$client.JComponent.roundRect": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 6 4"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox28"
"$client.JComponent.roundRect": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 4"
} )
add( new FormComponent( "javax.swing.JComboBox" ) { add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox9" name: "comboBox9"
"editable": true "editable": true