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`
|
||||
}
|
||||
|
||||
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 {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
@@ -52,6 +58,11 @@ tasks {
|
||||
named<Jar>( "javadocJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
}
|
||||
|
||||
flatlafPublish {
|
||||
|
||||
@@ -309,6 +309,9 @@ class LinuxFontPolicy
|
||||
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
||||
*/
|
||||
private static boolean isSystemScaling() {
|
||||
if( GraphicsEnvironment.isHeadless() )
|
||||
return true;
|
||||
|
||||
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
return UIScale.getSystemScaleFactor( gc ) > 1;
|
||||
|
||||
@@ -501,9 +501,9 @@ public class FlatButtonUI
|
||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
||||
// apply minimum width/height
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + Math.round( focusWidth * 2 ) );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + Math.round( focusWidth * 2 ) );
|
||||
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + fw );
|
||||
}
|
||||
|
||||
return prefSize;
|
||||
|
||||
@@ -534,7 +534,8 @@ public class FlatComboBoxUI
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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