mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
ComboBox: fixed minimum width if focusWidth > 0 (to be equal with button minimum width)
added some unit tests to compare component sizes
This commit is contained in:
@@ -21,6 +21,12 @@ plugins {
|
|||||||
`flatlaf-publish`
|
`flatlaf-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
|
||||||
|
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
|
||||||
|
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-params" )
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
@@ -52,6 +58,11 @@ tasks {
|
|||||||
named<Jar>( "javadocJar" ) {
|
named<Jar>( "javadocJar" ) {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName.set( "flatlaf" )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flatlafPublish {
|
flatlafPublish {
|
||||||
|
|||||||
@@ -309,6 +309,9 @@ class LinuxFontPolicy
|
|||||||
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
||||||
*/
|
*/
|
||||||
private static boolean isSystemScaling() {
|
private static boolean isSystemScaling() {
|
||||||
|
if( GraphicsEnvironment.isHeadless() )
|
||||||
|
return true;
|
||||||
|
|
||||||
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||||
return UIScale.getSystemScaleFactor( gc ) > 1;
|
return UIScale.getSystemScaleFactor( gc ) > 1;
|
||||||
|
|||||||
@@ -501,9 +501,9 @@ public class FlatButtonUI
|
|||||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||||
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
||||||
// apply minimum width/height
|
// apply minimum width/height
|
||||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + Math.round( focusWidth * 2 ) );
|
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + Math.round( focusWidth * 2 ) );
|
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + fw );
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefSize;
|
return prefSize;
|
||||||
|
|||||||
@@ -534,7 +534,8 @@ public class FlatComboBoxUI
|
|||||||
@Override
|
@Override
|
||||||
public Dimension getMinimumSize( JComponent c ) {
|
public Dimension getMinimumSize( JComponent c ) {
|
||||||
Dimension minimumSize = super.getMinimumSize( c );
|
Dimension minimumSize = super.getMinimumSize( c );
|
||||||
minimumSize.width = Math.max( minimumSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) );
|
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||||
|
minimumSize.width = Math.max( minimumSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||||
return minimumSize;
|
return minimumSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
import javax.swing.border.LineBorder;
|
||||||
|
import javax.swing.plaf.basic.BasicComboBoxEditor;
|
||||||
|
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class TestFlatComponentSizes
|
||||||
|
{
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() {
|
||||||
|
TestUtils.setup( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void cleanup() {
|
||||||
|
TestUtils.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static float[] factors() {
|
||||||
|
return new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 3f, 4f };
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void sizes( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
// TODO on some scale factors the combobox/spinner sizes are slightly different
|
||||||
|
// because different size calculation methods and rounding
|
||||||
|
boolean testComboBoxAndSpinner = (UIManager.getInt( "Component.focusWidth" ) > 0)
|
||||||
|
? (factor != 1.25 && factor != 2.25)
|
||||||
|
: (factor != 1.75);
|
||||||
|
|
||||||
|
|
||||||
|
// should have same default size (minimumWidth is 64)
|
||||||
|
JTextField textField = new JTextField();
|
||||||
|
JFormattedTextField formattedTextField = new JFormattedTextField();
|
||||||
|
JPasswordField passwordField = new JPasswordField();
|
||||||
|
JSpinner spinner = new JSpinner();
|
||||||
|
|
||||||
|
Dimension textFieldSize = textField.getPreferredSize();
|
||||||
|
assertEquals( textFieldSize, formattedTextField.getPreferredSize() );
|
||||||
|
assertEquals( textFieldSize, passwordField.getPreferredSize() );
|
||||||
|
if( testComboBoxAndSpinner )
|
||||||
|
assertEquals( textFieldSize, spinner.getPreferredSize() );
|
||||||
|
|
||||||
|
|
||||||
|
// should have same default size (minimumWidth is 72)
|
||||||
|
JButton button = new JButton( "text" );
|
||||||
|
JComboBox<String> comboBox = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBoxEditable = new JComboBox<>();
|
||||||
|
comboBoxEditable.setEditable( true );
|
||||||
|
|
||||||
|
Dimension buttonSize = button.getPreferredSize();
|
||||||
|
if( testComboBoxAndSpinner ) {
|
||||||
|
assertEquals( buttonSize, comboBox.getPreferredSize() );
|
||||||
|
assertEquals( buttonSize, comboBoxEditable.getPreferredSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// should have same height
|
||||||
|
JToggleButton toggleButton = new JToggleButton( "text" );
|
||||||
|
|
||||||
|
assertEquals( textFieldSize.height, button.getPreferredSize().height );
|
||||||
|
assertEquals( textFieldSize.height, toggleButton.getPreferredSize().height );
|
||||||
|
|
||||||
|
|
||||||
|
// should have same size
|
||||||
|
JCheckBox checkBox = new JCheckBox( "text" );
|
||||||
|
JRadioButton radioButton = new JRadioButton( "text" );
|
||||||
|
assertEquals( checkBox.getPreferredSize(), radioButton.getPreferredSize() );
|
||||||
|
|
||||||
|
|
||||||
|
// should have same size
|
||||||
|
JMenu menu = new JMenu( "text" );
|
||||||
|
JMenuItem menuItem = new JMenuItem( "text" );
|
||||||
|
JCheckBoxMenuItem checkBoxMenuItem = new JCheckBoxMenuItem( "text" );
|
||||||
|
JRadioButtonMenuItem radioButtonMenuItem = new JRadioButtonMenuItem( "text" );
|
||||||
|
|
||||||
|
Dimension menuSize = menu.getPreferredSize();
|
||||||
|
assertEquals( menuSize, menuItem.getPreferredSize() );
|
||||||
|
assertEquals( menuSize, checkBoxMenuItem.getPreferredSize() );
|
||||||
|
assertEquals( menuSize, radioButtonMenuItem.getPreferredSize() );
|
||||||
|
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void comboBox( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
JComboBox<String> comboBox = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox2 = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox3 = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox4 = new JComboBox<>();
|
||||||
|
|
||||||
|
applyCustomComboBoxRendererBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 3 ) ) );
|
||||||
|
applyCustomComboBoxRendererBorder( comboBox3, new BorderWithIcon() );
|
||||||
|
applyCustomComboBoxRendererBorder( comboBox4, null );
|
||||||
|
|
||||||
|
Dimension size = comboBox.getPreferredSize();
|
||||||
|
assertEquals( size, comboBox2.getPreferredSize() );
|
||||||
|
assertEquals( size, comboBox3.getPreferredSize() );
|
||||||
|
assertEquals( size, comboBox4.getPreferredSize() );
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
private void applyCustomComboBoxRendererBorder( JComboBox<String> comboBox, Border border ) {
|
||||||
|
BasicComboBoxRenderer customRenderer = new BasicComboBoxRenderer();
|
||||||
|
customRenderer.setBorder( border );
|
||||||
|
comboBox.setRenderer( customRenderer );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void comboBoxEditable( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
JComboBox<String> comboBox = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox2 = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox3 = new JComboBox<>();
|
||||||
|
JComboBox<String> comboBox4 = new JComboBox<>();
|
||||||
|
|
||||||
|
comboBox.setEditable( true );
|
||||||
|
comboBox2.setEditable( true );
|
||||||
|
comboBox3.setEditable( true );
|
||||||
|
comboBox4.setEditable( true );
|
||||||
|
|
||||||
|
applyCustomComboBoxEditorBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 3 ) ) );
|
||||||
|
applyCustomComboBoxEditorBorder( comboBox3, new BorderWithIcon() );
|
||||||
|
applyCustomComboBoxEditorBorder( comboBox4, null );
|
||||||
|
|
||||||
|
Dimension size = comboBox.getPreferredSize();
|
||||||
|
assertEquals( size.width, comboBox2.getPreferredSize().width );
|
||||||
|
assertEquals( size.height + (2 * UIScale.scale( 3 )), comboBox2.getPreferredSize().height );
|
||||||
|
assertEquals( size, comboBox3.getPreferredSize() );
|
||||||
|
assertEquals( size, comboBox4.getPreferredSize() );
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCustomComboBoxEditorBorder( JComboBox<String> comboBox, Border border ) {
|
||||||
|
JTextField customTextField = new JTextField();
|
||||||
|
if( border != null )
|
||||||
|
customTextField.setBorder( border );
|
||||||
|
comboBox.setEditor( new BasicComboBoxEditor() {
|
||||||
|
@Override
|
||||||
|
protected JTextField createEditorComponent() {
|
||||||
|
return customTextField;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class BorderWithIcon -----------------------------------------------
|
||||||
|
|
||||||
|
private static class BorderWithIcon
|
||||||
|
implements Border
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBorderOpaque() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Insets getBorderInsets( Component c ) {
|
||||||
|
return new Insets( 0, 0, 0, UIScale.scale( 16 ) + 4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class TestFlatComponentSizesWithFocus
|
||||||
|
extends TestFlatComponentSizes
|
||||||
|
{
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() {
|
||||||
|
TestUtils.setup( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class TestUtils
|
||||||
|
{
|
||||||
|
public static void setup( boolean withFocus ) {
|
||||||
|
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||||
|
if( withFocus )
|
||||||
|
FlatIntelliJLaf.setup();
|
||||||
|
else
|
||||||
|
FlatLightLaf.setup();
|
||||||
|
System.clearProperty( FlatSystemProperties.UI_SCALE );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanup() {
|
||||||
|
UIManager.put( "defaultFont", null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void scaleFont( float factor ) {
|
||||||
|
Font defaultFont = UIManager.getLookAndFeelDefaults().getFont( "defaultFont" );
|
||||||
|
UIManager.put( "defaultFont", defaultFont.deriveFont( (float) Math.round( defaultFont.getSize() * factor ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetFont() {
|
||||||
|
UIManager.put( "defaultFont", null );
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user