diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfc1a57c..1050dcf2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,36 @@
FlatLaf Change Log
==================
-## 1.3-SNAPSHOT
+## 1.4-SNAPSHOT
+
+#### New features and improvements
+
+- TextField, FormattedTextField and PasswordField: Support adding extra padding.
+ (set client property `JTextField.padding` to `Insets`).
+- PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI`
+ (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier
+ extensibility.
+
+#### Fixed bugs
+
+- 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)
+- 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
+ 8 only) so that Button, ComboBox, Spinner and TextField components (including
+ subclasses) have same heights. This increases heights of Button and TextField
+ components by:
+ - `2px` at `1.75x` in **Light** and **Dark** themes
+ - `2px` at `1.25x` and `2.25x` in **IntelliJ** and **Darcula** themes
+
+
+## 1.3
#### New features and improvements
@@ -10,13 +39,15 @@ FlatLaf Change Log
`PasswordField.focusedBackground`, `FormattedTextField.focusedBackground`,
`TextArea.focusedBackground`, `TextPane.focusedBackground`,
`EditorPane.focusedBackground`, `ComboBox.focusedBackground`,
- `ComboBox.buttonFocusedBackground`, `ComboBox.popupFocusedBackground` and
+ `ComboBox.buttonFocusedBackground`, `ComboBox.popupBackground` and
`Spinner.focusedBackground`). (issue #335)
#### Fixed bugs
- Fixed white lines at bottom and right side of window (in dark themes on HiDPI
screens with scaling enabled).
+- ScrollBar: Fixed left/top arrow icon location (if visible). (issue #329)
+- Spinner: Fixed up/down arrow icon location.
- ToolTip: Fixed positioning of huge tooltips. (issue #333)
diff --git a/build.gradle.kts b/build.gradle.kts
index d40e897e..4537b107 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-val releaseVersion = "1.2"
-val developmentVersion = "1.3-SNAPSHOT"
+val releaseVersion = "1.3"
+val developmentVersion = "1.4-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
diff --git a/flatlaf-core/build.gradle.kts b/flatlaf-core/build.gradle.kts
index 8ba273ee..97f2fab0 100644
--- a/flatlaf-core/build.gradle.kts
+++ b/flatlaf-core/build.gradle.kts
@@ -23,6 +23,7 @@ plugins {
dependencies {
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
+ testImplementation( "org.junit.jupiter:junit-jupiter-params" )
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
index 52032e36..8f107a42 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
@@ -743,6 +743,18 @@ public interface FlatClientProperties
*/
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
+ /**
+ * Specifies the padding of the text.
+ * This changes the location and size of the text view within the component bounds,
+ * but does not affect the size of the component.
+ *
+ * Component {@link javax.swing.JTextField} (and subclasses)
+ * Value type {@link java.awt.Insets}
+ *
+ * @since 1.4
+ */
+ String TEXT_FIELD_PADDING = "JTextField.padding";
+
//---- JToggleButton ------------------------------------------------------
/**
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/LinuxFontPolicy.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/LinuxFontPolicy.java
index b6417f13..b20fba54 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/LinuxFontPolicy.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/LinuxFontPolicy.java
@@ -128,7 +128,7 @@ class LinuxFontPolicy
// find last word in family
int index = family.lastIndexOf( ' ' );
if( index < 0 )
- return createFont( "Dialog", style, size, dsize );;
+ return createFont( "Dialog", style, size, dsize );
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
String lastWord = family.substring( index + 1 ).toLowerCase();
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java
index 288ef851..9f59f30d 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java
@@ -48,8 +48,8 @@ public class FlatArrowButton
protected Color pressedBackground;
private int arrowWidth = DEFAULT_ARROW_WIDTH;
- private int xOffset = 0;
- private int yOffset = 0;
+ private float xOffset = 0;
+ private float yOffset = 0;
private boolean hover;
private boolean pressed;
@@ -126,19 +126,19 @@ public class FlatArrowButton
return pressed;
}
- public int getXOffset() {
+ public float getXOffset() {
return xOffset;
}
- public void setXOffset( int xOffset ) {
+ public void setXOffset( float xOffset ) {
this.xOffset = xOffset;
}
- public int getYOffset() {
+ public float getYOffset() {
return yOffset;
}
- public void setYOffset( int yOffset ) {
+ public void setYOffset( float yOffset ) {
this.yOffset = yOffset;
}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java
index 49523483..25dc83cc 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java
@@ -184,13 +184,14 @@ public class FlatBorder
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
float focusWidth = scale( (float) getFocusWidth( c ) );
- float ow = focusWidth + scale( (float) getLineWidth( c ) );
+ int ow = Math.round( focusWidth + scale( (float) getLineWidth( c ) ) );
insets = super.getBorderInsets( c, insets );
- insets.top = Math.round( scale( (float) insets.top ) + ow );
- insets.left = Math.round( scale( (float) insets.left ) + ow );
- insets.bottom = Math.round( scale( (float) insets.bottom ) + ow );
- insets.right = Math.round( scale( (float) insets.right ) + ow );
+
+ insets.top = scale( insets.top ) + ow;
+ insets.left = scale( insets.left ) + ow;
+ insets.bottom = scale( insets.bottom ) + ow;
+ insets.right = scale( insets.right ) + ow;
if( isCellEditor( c ) ) {
// remove top and bottom insets if used as cell editor
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java
index 4daf92d7..f4134ea3 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java
@@ -569,9 +569,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;
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
index ba52ff4f..fe28e1c0 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.EventQueue;
+import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import javax.swing.JFormattedTextField;
@@ -61,6 +63,19 @@ public class FlatCaret
}
}
+ @Override
+ protected void adjustVisibility( Rectangle nloc ) {
+ JTextComponent c = getComponent();
+ if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
+ Insets padding = ((FlatTextFieldUI)c.getUI()).getPadding();
+ if( padding != null ) {
+ nloc.x -= padding.left;
+ nloc.y -= padding.top;
+ }
+ }
+ super.adjustVisibility( nloc );
+ }
+
@Override
public void focusGained( FocusEvent e ) {
if( !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java
index 146c4414..9064a227 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java
@@ -17,6 +17,7 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
+import static com.formdev.flatlaf.util.UIScale.unscale;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
@@ -39,7 +40,6 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeListener;
-import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.AbstractAction;
@@ -71,7 +71,6 @@ import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.util.SystemInfo;
-import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JComboBox}.
@@ -106,7 +105,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault ComboBox.buttonDisabledArrowColor Color
* @uiDefault ComboBox.buttonHoverArrowColor Color
* @uiDefault ComboBox.buttonPressedArrowColor Color
- * @uiDefault ComboBox.popupFocusedBackground Color optional
+ * @uiDefault ComboBox.popupBackground Color optional
*
* @author Karl Tauber
*/
@@ -134,13 +133,14 @@ public class FlatComboBoxUI
@Styleable protected Color buttonHoverArrowColor;
@Styleable protected Color buttonPressedArrowColor;
- @Styleable protected Color popupFocusedBackground;
+ @Styleable protected Color popupBackground;
private MouseListener hoverListener;
protected boolean hover;
protected boolean pressed;
- private WeakReference lastRendererComponent;
+ private CellPaddingBorder paddingBorder;
+
private Map oldStyleValues;
private AtomicBoolean borderShared;
@@ -227,15 +227,14 @@ public class FlatComboBoxUI
buttonHoverArrowColor = UIManager.getColor( "ComboBox.buttonHoverArrowColor" );
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
- popupFocusedBackground = UIManager.getColor( "ComboBox.popupFocusedBackground" );
+ popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
// set maximumRowCount
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
if( maximumRowCount > 0 && maximumRowCount != 8 && comboBox.getMaximumRowCount() == 8 )
comboBox.setMaximumRowCount( maximumRowCount );
- // scale
- padding = UIScale.scale( padding );
+ paddingBorder = new CellPaddingBorder( padding );
MigLayoutVisualPadding.install( comboBox );
}
@@ -260,7 +259,9 @@ public class FlatComboBoxUI
buttonHoverArrowColor = null;
buttonPressedArrowColor = null;
- popupFocusedBackground = null;
+ popupBackground = null;
+
+ paddingBorder.uninstall();
oldStyleValues = null;
borderShared = null;
@@ -291,11 +292,6 @@ public class FlatComboBoxUI
editor.setBounds( rectangleForCurrentValue() );
}
}
-
- if( editor != null && padding != null ) {
- // fix editor bounds by subtracting padding
- editor.setBounds( FlatUIUtils.subtractInsets( editor.getBounds(), padding ) );
- }
}
};
}
@@ -381,9 +377,13 @@ public class FlatComboBoxUI
protected void configureEditor() {
super.configureEditor();
- // remove default text field border from editor
- if( editor instanceof JTextField && ((JTextField)editor).getBorder() instanceof FlatTextBorder )
- ((JTextField)editor).setBorder( BorderFactory.createEmptyBorder() );
+ if( editor instanceof JTextField ) {
+ JTextField textField = (JTextField) editor;
+
+ // remove default text field border from editor
+ if( textField.getBorder() instanceof FlatTextBorder )
+ textField.setBorder( BorderFactory.createEmptyBorder() );
+ }
// explicitly make non-opaque
if( editor instanceof JComponent )
@@ -391,6 +391,7 @@ public class FlatComboBoxUI
editor.applyComponentOrientation( comboBox.getComponentOrientation() );
+ updateEditorPadding();
updateEditorColors();
// macOS
@@ -407,6 +408,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() {
// use non-UIResource colors because when SwingUtilities.updateComponentTreeUI()
// is used, then the editor is updated after the combobox and the
@@ -516,30 +536,24 @@ public class FlatComboBoxUI
@Override
@SuppressWarnings( "unchecked" )
public void paintCurrentValue( Graphics g, Rectangle bounds, boolean hasFocus ) {
+ paddingBorder.uninstall();
+
ListCellRenderer renderer = comboBox.getRenderer();
- uninstallCellPaddingBorder( renderer );
if( renderer == null )
renderer = new DefaultListCellRenderer();
Component c = renderer.getListCellRendererComponent( listBox, comboBox.getSelectedItem(), -1, false, false );
c.setFont( comboBox.getFont() );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
- uninstallCellPaddingBorder( c );
boolean enabled = comboBox.isEnabled();
c.setBackground( getBackground( enabled ) );
c.setForeground( getForeground( enabled ) );
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 );
+ paddingBorder.uninstall();
}
@Override
@@ -571,77 +585,50 @@ 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;
}
@Override
protected Dimension getDefaultSize() {
- @SuppressWarnings( "unchecked" )
- ListCellRenderer renderer = comboBox.getRenderer();
- uninstallCellPaddingBorder( renderer );
-
+ paddingBorder.uninstall();
Dimension size = super.getDefaultSize();
-
- uninstallCellPaddingBorder( renderer );
+ paddingBorder.uninstall();
return size;
}
@Override
protected Dimension getDisplaySize() {
- @SuppressWarnings( "unchecked" )
- ListCellRenderer renderer = comboBox.getRenderer();
- uninstallCellPaddingBorder( renderer );
+ paddingBorder.uninstall();
Dimension displaySize = super.getDisplaySize();
+ 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
- if( displaySize.width == 100 + padding.left + padding.right &&
+ if( displayWidth == 100 &&
comboBox.isEditable() &&
comboBox.getItemCount() == 0 &&
comboBox.getPrototypeDisplayValue() == null )
{
- int width = getDefaultSize().width;
- width = Math.max( width, editor.getPreferredSize().width );
- width += padding.left + padding.right;
- displaySize = new Dimension( width, displaySize.height );
+ displayWidth = Math.max( getDefaultSize().width, editor.getPreferredSize().width );
}
- uninstallCellPaddingBorder( renderer );
- return displaySize;
+ return new Dimension( displayWidth, displayHeight );
}
@Override
protected Dimension getSizeForComponent( Component comp ) {
+ paddingBorder.install( comp );
Dimension size = super.getSizeForComponent( comp );
-
- // 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 );
-
+ paddingBorder.uninstall();
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 void uninstallCellPaddingBorder( Object o ) {
- CellPaddingBorder.uninstall( o );
- if( lastRendererComponent != null ) {
- CellPaddingBorder.uninstall( lastRendererComponent );
- lastRendererComponent = null;
- }
- }
-
private boolean isCellRenderer() {
return comboBox.getParent() instanceof CellRendererPane;
}
@@ -652,6 +639,9 @@ public class FlatComboBoxUI
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
}
+ /**
+ * @since 1.3
+ */
public static boolean isPermanentFocusOwner( JComboBox> comboBox ) {
if( comboBox.isEditable() ) {
Component editorComponent = comboBox.getEditor().getEditorComponent();
@@ -707,13 +697,11 @@ public class FlatComboBoxUI
protected class FlatComboPopup
extends BasicComboPopup
{
- private CellPaddingBorder paddingBorder;
-
protected FlatComboPopup( JComboBox combo ) {
super( combo );
// 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
// orientation is not applied.
ComponentOrientation o = comboBox.getComponentOrientation();
@@ -781,8 +769,8 @@ public class FlatComboBoxUI
}
void updateStyle() {
- if( popupFocusedBackground != null )
- list.setBackground( popupFocusedBackground );
+ if( popupBackground != null )
+ list.setBackground( popupBackground );
}
@Override
@@ -796,6 +784,19 @@ public class FlatComboBoxUI
};
}
+ @Override
+ protected int getPopupHeightForRowCount( int maxRowCount ) {
+ int height = super.getPopupHeightForRowCount( maxRowCount );
+ paddingBorder.uninstall();
+ return height;
+ }
+
+ @Override
+ protected void paintChildren( Graphics g ) {
+ super.paintChildren( g );
+ paddingBorder.uninstall();
+ }
+
//---- class PopupListCellRenderer -----
private class PopupListCellRenderer
@@ -805,22 +806,15 @@ public class FlatComboBoxUI
public Component getListCellRendererComponent( JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus )
{
- ListCellRenderer renderer = comboBox.getRenderer();
- CellPaddingBorder.uninstall( renderer );
- CellPaddingBorder.uninstall( lastRendererComponent );
+ paddingBorder.uninstall();
+ ListCellRenderer renderer = comboBox.getRenderer();
if( renderer == null )
renderer = new DefaultListCellRenderer();
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
- if( c instanceof JComponent ) {
- if( paddingBorder == null )
- paddingBorder = new CellPaddingBorder( padding );
- paddingBorder.install( (JComponent) c );
- }
-
- lastRendererComponent = (c != renderer) ? new WeakReference<>( c ) : null;
+ paddingBorder.install( c );
return c;
}
@@ -830,49 +824,63 @@ public class FlatComboBoxUI
//---- class CellPaddingBorder --------------------------------------------
/**
- * Cell padding border used only in popup list.
- *
+ * Cell padding border used in popup list and for current value if not editable.
+ *
* 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.
- *
- * The renderer border is painted on the outside of this border.
+ *
+ * The renderer border is painted on the outer side of this border.
*/
private static class CellPaddingBorder
extends AbstractBorder
{
private final Insets padding;
+ private JComponent rendererComponent;
private Border rendererBorder;
CellPaddingBorder( Insets padding ) {
this.padding = padding;
}
- void install( JComponent rendererComponent ) {
- Border oldBorder = rendererComponent.getBorder();
- if( !(oldBorder instanceof CellPaddingBorder) ) {
- rendererBorder = oldBorder;
- rendererComponent.setBorder( this );
- }
- }
-
- static void uninstall( Object o ) {
- if( o instanceof WeakReference )
- o = ((WeakReference>)o).get();
-
- if( !(o instanceof JComponent) )
+ void install( Component c ) {
+ if( !(c instanceof JComponent) )
return;
- JComponent rendererComponent = (JComponent) o;
- Border border = rendererComponent.getBorder();
- if( border instanceof CellPaddingBorder ) {
- CellPaddingBorder paddingBorder = (CellPaddingBorder) border;
- rendererComponent.setBorder( paddingBorder.rendererBorder );
- paddingBorder.rendererBorder = null;
- }
+ JComponent jc = (JComponent) c;
+ Border oldBorder = jc.getBorder();
+ if( oldBorder == this )
+ return; // already installed
+
+ // this border can be installed only at one component
+ uninstall();
+
+ // remember component where this border was installed for uninstall
+ rendererComponent = jc;
+
+ // remember old border and replace it
+ rendererBorder = oldBorder;
+ rendererComponent.setBorder( this );
+ }
+
+ /**
+ * Uninstall border from previously installed component.
+ * Because this border is installed in PopupListCellRenderer.getListCellRendererComponent(),
+ * there is no single place to uninstall it.
+ * This is the reason why this method is called from various places.
+ */
+ void uninstall() {
+ if( rendererComponent == null )
+ return;
+
+ if( rendererComponent.getBorder() == this )
+ rendererComponent.setBorder( rendererBorder );
+ rendererComponent = null;
+ rendererBorder = null;
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
+ Insets padding = scale( this.padding );
if( rendererBorder != null ) {
Insets insideInsets = rendererBorder.getBorderInsets( c );
insets.top = Math.max( padding.top, insideInsets.top );
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java
index 11d91245..a016d7da 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java
@@ -39,8 +39,6 @@ import javax.swing.plaf.ComponentUI;
*
*
*
- * @uiDefault TextComponent.arc int
- * @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault FormattedTextField.placeholderForeground Color
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
index d81c267a..f14cf1f7 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
@@ -16,34 +16,32 @@
package com.formdev.flatlaf.ui;
-import java.awt.Color;
-import java.awt.Dimension;
import java.awt.Graphics;
-import java.awt.Graphics2D;
+import java.awt.Shape;
import java.awt.Toolkit;
-import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
-import java.beans.PropertyChangeEvent;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
-import javax.swing.plaf.basic.BasicPasswordFieldUI;
-import javax.swing.text.Caret;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
+import javax.swing.text.PasswordView;
+import javax.swing.text.View;
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
-import com.formdev.flatlaf.util.HiDPIUtils;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}.
*
- *
+ *
*
* @uiDefault PasswordField.font Font
* @uiDefault PasswordField.background Color
@@ -56,42 +54,32 @@ import com.formdev.flatlaf.util.HiDPIUtils;
* @uiDefault PasswordField.inactiveForeground Color used if not enabled (yes, this is confusing; this should be named disabledForeground)
* @uiDefault PasswordField.border Border
* @uiDefault PasswordField.margin Insets
- * @uiDefault PasswordField.echoChar character
* @uiDefault PasswordField.caretBlinkRate int default is 500 milliseconds
*
- *
+ *
*
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault PasswordField.placeholderForeground Color
* @uiDefault PasswordField.focusedBackground Color optional
- * @uiDefault PasswordField.showCapsLock boolean
- * @uiDefault PasswordField.capsLockIcon Icon
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
* @uiDefault TextComponent.selectAllOnMouseClick boolean
*
+ *
+ *
+ * @uiDefault PasswordField.echoChar character
+ * @uiDefault PasswordField.showCapsLock boolean
+ * @uiDefault PasswordField.capsLockIcon Icon
+ *
* @author Karl Tauber
*/
public class FlatPasswordFieldUI
- extends BasicPasswordFieldUI
+ extends FlatTextFieldUI
{
- @Styleable protected int minimumWidth;
- protected boolean isIntelliJTheme;
- private Color background;
- @Styleable protected Color disabledBackground;
- @Styleable protected Color inactiveBackground;
- @Styleable protected Color placeholderForeground;
- @Styleable protected Color focusedBackground;
@Styleable protected boolean showCapsLock;
protected Icon capsLockIcon;
- private Color oldDisabledBackground;
- private Color oldInactiveBackground;
-
- private FocusListener focusListener;
private KeyListener capsLockListener;
- private Map oldStyleValues;
- private AtomicBoolean borderShared;
private boolean capsLockIconShared = true;
public static ComponentUI createUI( JComponent c ) {
@@ -99,10 +87,8 @@ public class FlatPasswordFieldUI
}
@Override
- public void installUI( JComponent c ) {
- super.installUI( c );
-
- applyStyle( FlatStyleSupport.getStyle( c ) );
+ protected String getPropertyPrefix() {
+ return "PasswordField";
}
@Override
@@ -110,48 +96,25 @@ public class FlatPasswordFieldUI
super.installDefaults();
String prefix = getPropertyPrefix();
- minimumWidth = UIManager.getInt( "Component.minimumWidth" );
- isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
- background = UIManager.getColor( prefix + ".background" );
- disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
- inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
- placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
- focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
+ Character echoChar = (Character) UIManager.get( prefix + ".echoChar" );
+ if( echoChar != null )
+ LookAndFeel.installProperty( getComponent(), "echoChar", echoChar );
+
showCapsLock = UIManager.getBoolean( "PasswordField.showCapsLock" );
capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" );
-
- LookAndFeel.installProperty( getComponent(), "opaque", false );
-
- MigLayoutVisualPadding.install( getComponent() );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
- background = null;
- disabledBackground = null;
- inactiveBackground = null;
- placeholderForeground = null;
- focusedBackground = null;
capsLockIcon = null;
-
- oldDisabledBackground = null;
- oldInactiveBackground = null;
-
- oldStyleValues = null;
- borderShared = null;
-
- MigLayoutVisualPadding.uninstall( getComponent() );
}
@Override
protected void installListeners() {
super.installListeners();
- // necessary to update focus border and background
- focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
-
// update caps lock indicator
capsLockListener = new KeyAdapter() {
@Override
@@ -168,7 +131,6 @@ public class FlatPasswordFieldUI
}
};
- getComponent().addFocusListener( focusListener );
getComponent().addKeyListener( capsLockListener );
}
@@ -176,43 +138,24 @@ public class FlatPasswordFieldUI
protected void uninstallListeners() {
super.uninstallListeners();
- getComponent().removeFocusListener( focusListener );
getComponent().removeKeyListener( capsLockListener );
- focusListener = null;
capsLockListener = null;
}
@Override
- protected Caret createCaret() {
- return new FlatCaret( UIManager.getString( "TextComponent.selectAllOnFocusPolicy" ),
- UIManager.getBoolean( "TextComponent.selectAllOnMouseClick" ) );
+ protected void installKeyboardActions() {
+ super.installKeyboardActions();
+
+ // map "select-word" action (double-click) to "select-line" action
+ ActionMap map = SwingUtilities.getUIActionMap( getComponent() );
+ if( map != null && map.get( DefaultEditorKit.selectWordAction ) != null ) {
+ Action selectLineAction = map.get( DefaultEditorKit.selectLineAction );
+ if( selectLineAction != null )
+ map.put( DefaultEditorKit.selectWordAction, selectLineAction );
+ }
}
@Override
- protected void propertyChange( PropertyChangeEvent e ) {
- String propertyName = e.getPropertyName();
- if( "editable".equals( propertyName ) || "enabled".equals( propertyName ) )
- updateBackground();
- else
- super.propertyChange( e );
- FlatTextFieldUI.propertyChange( getComponent(), e, this::applyStyle );
- }
-
- /**
- * @since TODO
- */
- protected void applyStyle( Object style ) {
- oldDisabledBackground = disabledBackground;
- oldInactiveBackground = inactiveBackground;
-
- oldStyleValues = FlatStyleSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
-
- updateBackground();
- }
-
- /**
- * @since TODO
- */
protected Object applyStyleProperty( String key, Object value ) {
if( key.equals( "capsLockIconColor" ) && capsLockIcon instanceof FlatCapsLockIcon ) {
if( capsLockIconShared ) {
@@ -222,24 +165,23 @@ public class FlatPasswordFieldUI
return ((FlatCapsLockIcon)capsLockIcon).applyStyleProperty( key, value );
}
- if( borderShared == null )
- borderShared = new AtomicBoolean( true );
- return FlatStyleSupport.applyToAnnotatedObjectOrBorder( this, key, value, getComponent(), borderShared );
+ return super.applyStyleProperty( key, value );
}
- private void updateBackground() {
- FlatTextFieldUI.updateBackground( getComponent(), background,
- disabledBackground, inactiveBackground,
- oldDisabledBackground, oldInactiveBackground );
+ @Override
+ public View create( Element elem ) {
+ return new PasswordView( elem );
}
@Override
protected void paintSafely( Graphics g ) {
- FlatTextFieldUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
- FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
- paintCapsLock( g );
+ // safe and restore clipping area because super.paintSafely() modifies it
+ // and the caps lock icon would be truncated
+ Shape oldClip = g.getClip();
+ super.paintSafely( g );
+ g.setClip( oldClip );
- super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
+ paintCapsLock( g );
}
protected void paintCapsLock( Graphics g ) {
@@ -255,19 +197,4 @@ public class FlatPasswordFieldUI
int x = c.getWidth() - capsLockIcon.getIconWidth() - y;
capsLockIcon.paintIcon( c, g, x, y );
}
-
- @Override
- protected void paintBackground( Graphics g ) {
- // background is painted elsewhere
- }
-
- @Override
- public Dimension getPreferredSize( JComponent c ) {
- return FlatTextFieldUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
- }
-
- @Override
- public Dimension getMinimumSize( JComponent c ) {
- return FlatTextFieldUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
- }
}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java
index 38627b54..bd406d4a 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java
@@ -369,6 +369,9 @@ public class FlatScrollPaneUI
paint( g, c );
}
+ /**
+ * @since 1.3
+ */
public static boolean isPermanentFocusOwner( JScrollPane scrollPane ) {
JViewport viewport = scrollPane.getViewport();
Component view = (viewport != null) ? viewport.getView() : null;
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java
index c230a82f..c37691fc 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java
@@ -214,6 +214,7 @@ public class FlatSpinnerUI
if( textField != null )
textField.setOpaque( false );
+ updateEditorPadding();
updateEditorColors();
return editor;
}
@@ -224,6 +225,8 @@ public class FlatSpinnerUI
removeEditorFocusListener( oldEditor );
addEditorFocusListener( newEditor );
+
+ updateEditorPadding();
updateEditorColors();
}
@@ -239,6 +242,12 @@ public class FlatSpinnerUI
textField.removeFocusListener( getHandler() );
}
+ private void updateEditorPadding() {
+ JTextField textField = getEditorTextField( spinner.getEditor() );
+ if( textField != null )
+ textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding );
+ }
+
private void updateEditorColors() {
JTextField textField = getEditorTextField( spinner.getEditor() );
if( textField != null ) {
@@ -256,6 +265,9 @@ public class FlatSpinnerUI
: null;
}
+ /**
+ * @since 1.3
+ */
public static boolean isPermanentFocusOwner( JSpinner spinner ) {
if( FlatUIUtils.isPermanentFocusOwner( spinner ) )
return true;
@@ -306,7 +318,7 @@ public class FlatSpinnerUI
FlatArrowButton button = new FlatArrowButton( direction, arrowType, buttonArrowColor,
buttonDisabledArrowColor, buttonHoverArrowColor, null, buttonPressedArrowColor, null );
button.setName( name );
- button.setYOffset( (direction == SwingConstants.NORTH) ? 1 : -1 );
+ button.setYOffset( (direction == SwingConstants.NORTH) ? 1.25f : -1.25f );
if( direction == SwingConstants.NORTH )
installNextButtonListeners( button );
else
@@ -435,7 +447,7 @@ public class FlatSpinnerUI
if( nextButton == null && previousButton == null ) {
if( editor != null )
- editor.setBounds( FlatUIUtils.subtractInsets( r, padding ) );
+ editor.setBounds( r );
return;
}
@@ -455,7 +467,7 @@ public class FlatSpinnerUI
}
if( editor != null )
- editor.setBounds( FlatUIUtils.subtractInsets( editorRect, padding ) );
+ editor.setBounds( editorRect );
int nextHeight = (buttonsRect.height / 2) + (buttonsRect.height % 2); // round up
if( nextButton != null )
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java
index fce393f2..8f7e47ff 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java
@@ -24,6 +24,7 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.util.Map;
@@ -44,6 +45,7 @@ import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.JavaCompatibility;
+import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
@@ -177,6 +179,7 @@ public class FlatTextFieldUI
switch( e.getPropertyName() ) {
case FlatClientProperties.PLACEHOLDER_TEXT:
case FlatClientProperties.COMPONENT_ROUND_RECT:
+ case FlatClientProperties.TEXT_FIELD_PADDING:
c.repaint();
break;
@@ -294,14 +297,14 @@ public class FlatTextFieldUI
if( !(background instanceof UIResource) )
return background;
+ // focused
+ if( focusedBackground != null && FlatUIUtils.isPermanentFocusOwner( c ) )
+ return focusedBackground;
+
// for compatibility with IntelliJ themes
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) )
return FlatUIUtils.getParentBackground( c );
- // focused and editable
- if( focusedBackground != null && c.isEditable() && FlatUIUtils.isPermanentFocusOwner( c ) )
- return focusedBackground;
-
return background;
}
@@ -359,4 +362,27 @@ public class FlatTextFieldUI
size.width = Math.max( size.width, scale( minimumWidth ) + Math.round( focusWidth * 2 ) );
return size;
}
+
+ @Override
+ protected Rectangle getVisibleEditorRect() {
+ Rectangle r = super.getVisibleEditorRect();
+ if( r != null ) {
+ // remove padding
+ Insets padding = getPadding();
+ if( padding != null ) {
+ r = FlatUIUtils.subtractInsets( r, padding );
+ r.width = Math.max( r.width, 0 );
+ r.height = Math.max( r.height, 0 );
+ }
+ }
+ return r;
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected Insets getPadding() {
+ Object padding = getComponent().getClientProperty( FlatClientProperties.TEXT_FIELD_PADDING );
+ return (padding instanceof Insets) ? UIScale.scale( (Insets) padding ) : null;
+ }
}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java
index 4e3cf598..39a22ebe 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java
@@ -660,7 +660,7 @@ public class FlatUIUtils
* @since 1.1
*/
public static void paintArrow( Graphics2D g, int x, int y, int width, int height,
- int direction, boolean chevron, int arrowSize, int xOffset, int yOffset )
+ int direction, boolean chevron, int arrowSize, float xOffset, float yOffset )
{
// compute arrow width/height
int aw = UIScale.scale( arrowSize + (chevron ? 0 : 1) );
@@ -679,8 +679,10 @@ public class FlatUIUtils
int extra = chevron ? 1 : 0;
// compute arrow location
- int ax = x + Math.round( ((width - (aw + extra)) / 2f) + UIScale.scale( (float) xOffset ) );
- int ay = y + Math.round( ((height - (ah + extra)) / 2f) + UIScale.scale( (float) yOffset ) );
+ float ox = ((width - (aw + extra)) / 2f) + UIScale.scale( xOffset );
+ float oy = ((height - (ah + extra)) / 2f) + UIScale.scale( yOffset );
+ int ax = x + ((direction == SwingConstants.WEST) ? -Math.round( -ox ) : Math.round( ox ));
+ int ay = y + ((direction == SwingConstants.NORTH) ? -Math.round( -oy ) : Math.round( oy ));
// paint arrow
g.translate( ax, ay );
diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/FlatStylingTests.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/FlatStylingTests.java
index 58645e39..687ffa2e 100644
--- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/FlatStylingTests.java
+++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/FlatStylingTests.java
@@ -164,7 +164,7 @@ public class FlatStylingTests
ui.applyStyle( "buttonHoverArrowColor: #fff" );
ui.applyStyle( "buttonPressedArrowColor: #fff" );
- ui.applyStyle( "popupFocusedBackground: #fff" );
+ ui.applyStyle( "popupBackground: #fff" );
// border
flatRoundBorder( style -> ui.applyStyle( style ) );
diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizes.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizes.java
new file mode 100644
index 00000000..02f559a8
--- /dev/null
+++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizes.java
@@ -0,0 +1,203 @@
+/*
+ * 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 TestUtils.FACTORS;
+ }
+
+ @ParameterizedTest
+ @MethodSource( "factors" )
+ void sizes( float factor ) {
+ TestUtils.scaleFont( factor );
+
+
+ // 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() );
+ assertEquals( textFieldSize, spinner.getPreferredSize() );
+
+
+ // should have same default size (minimumWidth is 72)
+ JButton button = new JButton( "text" );
+ JComboBox comboBox = new JComboBox<>();
+ JComboBox comboBoxEditable = new JComboBox<>();
+ comboBoxEditable.setEditable( true );
+
+ Dimension buttonSize = button.getPreferredSize();
+ 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 );
+
+ String[] items = { "t" };
+ JComboBox comboBox = new JComboBox<>( items );
+ JComboBox comboBox2 = new JComboBox<>( items );
+ JComboBox comboBox3 = new JComboBox<>( items );
+ JComboBox comboBox4 = new JComboBox<>( items );
+
+ applyCustomComboBoxRendererBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 6 ) ) );
+ applyCustomComboBoxRendererBorder( comboBox3, new BorderWithIcon() );
+ applyCustomComboBoxRendererBorder( comboBox4, null );
+
+ Dimension size = comboBox.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, comboBox4.getPreferredSize() );
+
+ TestUtils.resetFont();
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private void applyCustomComboBoxRendererBorder( JComboBox comboBox, Border border ) {
+ BasicComboBoxRenderer customRenderer = new BasicComboBoxRenderer();
+ customRenderer.setBorder( border );
+ comboBox.setRenderer( customRenderer );
+ }
+
+ @ParameterizedTest
+ @MethodSource( "factors" )
+ void comboBoxEditable( float factor ) {
+ TestUtils.scaleFont( factor );
+
+ String[] items = { "t" };
+ JComboBox comboBox = new JComboBox<>( items );
+ JComboBox comboBox2 = new JComboBox<>( items );
+ JComboBox comboBox3 = new JComboBox<>( items );
+ JComboBox comboBox4 = new JComboBox<>( items );
+
+ comboBox.setEditable( true );
+ comboBox2.setEditable( true );
+ comboBox3.setEditable( true );
+ comboBox4.setEditable( true );
+
+ applyCustomComboBoxEditorBorder( comboBox2, new LineBorder( Color.orange, UIScale.scale( 6 ) ) );
+ applyCustomComboBoxEditorBorder( comboBox3, new BorderWithIcon() );
+ applyCustomComboBoxEditorBorder( comboBox4, null );
+
+ Dimension size = comboBox.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, comboBox4.getPreferredSize() );
+
+ TestUtils.resetFont();
+ }
+
+ private void applyCustomComboBoxEditorBorder( JComboBox 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 );
+ }
+ }
+}
diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizesWithFocus.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizesWithFocus.java
new file mode 100644
index 00000000..074cacd7
--- /dev/null
+++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatComponentSizesWithFocus.java
@@ -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 );
+ }
+}
diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestUtils.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestUtils.java
new file mode 100644
index 00000000..e4bead06
--- /dev/null
+++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestUtils.java
@@ -0,0 +1,53 @@
+/*
+ * 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 final float[] FACTORS = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
+
+ 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 );
+ }
+}
diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java
index 8bd74b3a..48b3f3ef 100644
--- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java
+++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java
@@ -44,6 +44,7 @@ import java.awt.event.WindowListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
@@ -64,6 +65,7 @@ import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatUIUtils;
+import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -478,9 +480,17 @@ public class FlatInspector
if( c instanceof JComponent ) {
try {
- Field f = JComponent.class.getDeclaredField( "ui" );
- f.setAccessible( true );
- Object ui = f.get( c );
+ Object ui;
+ if( SystemInfo.isJava_9_orLater ) {
+ // Java 9+: use public method JComponent.getUI()
+ Method m = JComponent.class.getMethod( "getUI" );
+ ui = m.invoke( c );
+ } else {
+ // Java 8: read protected field 'ui'
+ Field f = JComponent.class.getDeclaredField( "ui" );
+ f.setAccessible( true );
+ ui = f.get( c );
+ }
appendRow( buf, "UI", (ui != null ? toString( ui.getClass(), classHierarchy ) : "null") );
} catch( Exception ex ) {
// ignore
@@ -553,6 +563,9 @@ public class FlatInspector
String simpleName = (dot >= 0) ? name.substring( dot + 1 ) : name;
buf.append( simpleName ).append( ' ' ).append( toDimmedText( "(" + pkg + ")" ) );
+ if( UIResource.class.isAssignableFrom( cls ) )
+ buf.append( " UI" );
+
if( !classHierarchy )
break;
@@ -613,11 +626,14 @@ public class FlatInspector
String s = toString( b.getClass(), classHierarchy );
- if( b instanceof EmptyBorder )
- s += '(' + toString( ((EmptyBorder)b).getBorderInsets() ) + ')';
-
- if( b instanceof UIResource )
- s += " UI";
+ if( b instanceof EmptyBorder ) {
+ String borderInsets = " (" + toString( ((EmptyBorder)b).getBorderInsets() ) + ')';
+ int brIndex = s.indexOf( " " );
+ if( brIndex >= 0 )
+ s = s.substring( 0, brIndex ) + borderInsets + s.substring( brIndex );
+ else
+ s += borderInsets;
+ }
return s;
}
diff --git a/flatlaf-jide-oss/build.gradle.kts b/flatlaf-jide-oss/build.gradle.kts
index a78027f3..397d8c7a 100644
--- a/flatlaf-jide-oss/build.gradle.kts
+++ b/flatlaf-jide-oss/build.gradle.kts
@@ -23,7 +23,7 @@ dependencies {
implementation( project( ":flatlaf-core" ) )
// use compileOnly() because there are various JIDE libraries available on Maven Central
- compileOnly( "com.formdev:jide-oss:3.7.11.1" )
+ compileOnly( "com.formdev:jide-oss:3.7.12" )
}
java {
diff --git a/flatlaf-testing/build.gradle.kts b/flatlaf-testing/build.gradle.kts
index 953491c8..53b51367 100644
--- a/flatlaf-testing/build.gradle.kts
+++ b/flatlaf-testing/build.gradle.kts
@@ -33,7 +33,7 @@ dependencies {
implementation( "com.jgoodies:jgoodies-forms:1.9.0" )
implementation( "org.swinglabs.swingx:swingx-all:1.6.5-1" )
implementation( "org.swinglabs.swingx:swingx-beaninfo:1.6.5-1" )
- implementation( "com.formdev:jide-oss:3.7.11.1" )
+ implementation( "com.formdev:jide-oss:3.7.12" )
implementation( "com.glazedlists:glazedlists:1.11.0" )
implementation( "org.netbeans.api:org-openide-awt:RELEASE112" )
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatAnimatedIconTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatAnimatedIconTest.java
index 0bf90add..160caca6 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatAnimatedIconTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatAnimatedIconTest.java
@@ -147,7 +147,7 @@ public class FlatAnimatedIconTest
@Override
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
- Color color = ColorFunctions.mix( onColor, offColor, animatedValue );;
+ Color color = ColorFunctions.mix( onColor, offColor, animatedValue );
// border
g.setColor( color );
@@ -190,7 +190,7 @@ public class FlatAnimatedIconTest
@Override
public void paintIconAnimated( Component c, Graphics g, int x, int y, float animatedValue ) {
- Color color = ColorFunctions.mix( onColor, offColor, animatedValue );;
+ Color color = ColorFunctions.mix( onColor, offColor, animatedValue );
g.setColor( color );
g.fillRoundRect( x, y, width, height, height, height );
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.java
index 22a4851c..028a8eea 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.java
@@ -51,6 +51,7 @@ public class FlatBaselineTest
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JPasswordField passwordField1 = new JPasswordField();
JComboBox comboBox1 = new JComboBox<>();
+ JComboBox comboBox2 = new JComboBox<>();
JSpinner spinner1 = new JSpinner();
JLabel label6 = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
@@ -88,7 +89,7 @@ public class FlatBaselineTest
//======== this ========
setLayout(new MigLayout(
- "insets dialog,hidemode 3,debug",
+ "insets dialog,hidemode 3",
// columns
"[fill]" +
"[fill]" +
@@ -96,6 +97,7 @@ public class FlatBaselineTest
"[fill]" +
"[fill]" +
"[fill]" +
+ "[fill]" +
"[fill]",
// rows
"[]" +
@@ -130,7 +132,7 @@ public class FlatBaselineTest
//---- textField4 ----
textField4.setText("Dext field");
- add(textField4, "cell 6 0");
+ add(textField4, "cell 7 0");
//---- label2 ----
label2.setText("Dext");
@@ -147,8 +149,20 @@ public class FlatBaselineTest
//---- passwordField1 ----
passwordField1.setText("Dext");
add(passwordField1, "cell 3 1");
+
+ //---- comboBox1 ----
+ comboBox1.setModel(new DefaultComboBoxModel<>(new String[] {
+ "Dext"
+ }));
add(comboBox1, "cell 4 1");
- add(spinner1, "cell 5 1");
+
+ //---- comboBox2 ----
+ comboBox2.setModel(new DefaultComboBoxModel<>(new String[] {
+ "Dext"
+ }));
+ comboBox2.setEditable(true);
+ add(comboBox2, "cell 5 1");
+ add(spinner1, "cell 6 1");
//---- label6 ----
label6.setText("Dext");
@@ -171,7 +185,7 @@ public class FlatBaselineTest
//---- textField2 ----
textField2.setText("Dext field");
- add(textField2, "cell 6 2");
+ add(textField2, "cell 7 2");
//---- label7 ----
label7.setText("Dext");
@@ -230,18 +244,18 @@ public class FlatBaselineTest
//---- textField3 ----
textField3.setText("Dext field");
- add(textField3, "cell 6 3");
+ add(textField3, "cell 7 3");
//---- label3 ----
label3.setText("Dext");
add(label3, "cell 0 4");
- add(slider1, "cell 1 4 6 1");
+ add(slider1, "cell 1 4 7 1");
//---- slider6 ----
slider6.setPaintTicks(true);
slider6.setMajorTickSpacing(25);
slider6.setMinorTickSpacing(5);
- add(slider6, "cell 1 4 6 1");
+ add(slider6, "cell 1 4 7 1");
//---- label8 ----
label8.setText("Dext");
@@ -251,14 +265,14 @@ public class FlatBaselineTest
slider7.setPaintLabels(true);
slider7.setMajorTickSpacing(25);
slider7.setMinorTickSpacing(5);
- add(slider7, "cell 1 5 6 1");
+ add(slider7, "cell 1 5 7 1");
//---- slider8 ----
slider8.setPaintLabels(true);
slider8.setPaintTicks(true);
slider8.setMajorTickSpacing(25);
slider8.setMinorTickSpacing(5);
- add(slider8, "cell 1 5 6 1");
+ add(slider8, "cell 1 5 7 1");
//---- label4 ----
label4.setText("Dext");
@@ -266,13 +280,13 @@ public class FlatBaselineTest
//---- progressBar1 ----
progressBar1.setValue(30);
- add(progressBar1, "cell 1 6 6 1");
+ add(progressBar1, "cell 1 6 7 1");
//---- progressBar3 ----
progressBar3.setStringPainted(true);
progressBar3.setValue(30);
- add(progressBar3, "cell 1 6 6 1");
- add(separator1, "cell 1 6 6 1");
+ add(progressBar3, "cell 1 6 7 1");
+ add(separator1, "cell 1 6 7 1");
//---- label5 ----
label5.setText("Dext");
@@ -280,26 +294,26 @@ public class FlatBaselineTest
//---- slider2 ----
slider2.setOrientation(SwingConstants.VERTICAL);
- add(slider2, "cell 1 7 6 1");
+ add(slider2, "cell 1 7 7 1");
//---- slider3 ----
slider3.setOrientation(SwingConstants.VERTICAL);
slider3.setPaintTicks(true);
slider3.setMajorTickSpacing(25);
slider3.setMinorTickSpacing(5);
- add(slider3, "cell 1 7 6 1");
+ add(slider3, "cell 1 7 7 1");
//---- progressBar2 ----
progressBar2.setOrientation(SwingConstants.VERTICAL);
progressBar2.setValue(30);
- add(progressBar2, "cell 1 7 6 1");
+ add(progressBar2, "cell 1 7 7 1");
//---- progressBar4 ----
progressBar4.setOrientation(SwingConstants.VERTICAL);
progressBar4.setStringPainted(true);
progressBar4.setValue(30);
- add(progressBar4, "cell 1 7 6 1");
- add(hSpacer1, "cell 1 7 6 1,growx");
+ add(progressBar4, "cell 1 7 7 1");
+ add(hSpacer1, "cell 1 7 7 1,growx");
//---- label9 ----
label9.setText("Dext");
@@ -310,7 +324,7 @@ public class FlatBaselineTest
slider4.setPaintLabels(true);
slider4.setMajorTickSpacing(25);
slider4.setMinorTickSpacing(5);
- add(slider4, "cell 1 8 6 1");
+ add(slider4, "cell 1 8 7 1");
//---- slider5 ----
slider5.setOrientation(SwingConstants.VERTICAL);
@@ -318,8 +332,8 @@ public class FlatBaselineTest
slider5.setPaintTicks(true);
slider5.setMajorTickSpacing(25);
slider5.setMinorTickSpacing(5);
- add(slider5, "cell 1 8 6 1");
- add(hSpacer2, "cell 1 8 6 1,growx");
+ add(slider5, "cell 1 8 7 1");
+ add(hSpacer2, "cell 1 8 7 1,growx");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.jfd
index b41f8d16..21df15b5 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.jfd
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatBaselineTest.jfd
@@ -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 {
contentType: "form/swing"
@@ -7,8 +7,8 @@ new FormModel {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
- "$layoutConstraints": "insets dialog,hidemode 3,debug"
- "$columnConstraints": "[fill][fill][fill][fill][fill][fill][fill]"
+ "$layoutConstraints": "insets dialog,hidemode 3"
+ "$columnConstraints": "[fill][fill][fill][fill][fill][fill][fill][fill]"
"$rowConstraints": "[][][50][::80][][][][][]"
} ) {
name: "this"
@@ -46,7 +46,7 @@ new FormModel {
name: "textField4"
"text": "Dext field"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 6 0"
+ "value": "cell 7 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
@@ -74,16 +74,33 @@ new FormModel {
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox1"
+ "model": new javax.swing.DefaultComboBoxModel {
+ selectedItem: "Dext"
+ addElement( "Dext" )
+ }
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 1"
} )
+ add( new FormComponent( "javax.swing.JComboBox" ) {
+ name: "comboBox2"
+ "model": new javax.swing.DefaultComboBoxModel {
+ selectedItem: "Dext"
+ addElement( "Dext" )
+ }
+ "editable": true
+ auxiliary() {
+ "JavaCodeGenerator.typeParameters": "String"
+ }
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 5 1"
+ } )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 5 1"
+ "value": "cell 6 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label6"
@@ -112,7 +129,7 @@ new FormModel {
name: "textField2"
"text": "Dext field"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 6 2"
+ "value": "cell 7 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label7"
@@ -184,7 +201,7 @@ new FormModel {
name: "textField3"
"text": "Dext field"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 6 3"
+ "value": "cell 7 3"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
@@ -195,7 +212,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 4 6 1"
+ "value": "cell 1 4 7 1"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider6"
@@ -203,7 +220,7 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 4 6 1"
+ "value": "cell 1 4 7 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label8"
@@ -217,7 +234,7 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 5 6 1"
+ "value": "cell 1 5 7 1"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider8"
@@ -226,7 +243,7 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 5 6 1"
+ "value": "cell 1 5 7 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
@@ -238,19 +255,19 @@ new FormModel {
name: "progressBar1"
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 6 6 1"
+ "value": "cell 1 6 7 1"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar3"
"stringPainted": true
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 6 6 1"
+ "value": "cell 1 6 7 1"
} )
add( new FormComponent( "javax.swing.JSeparator" ) {
name: "separator1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 6 6 1"
+ "value": "cell 1 6 7 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label5"
@@ -262,7 +279,7 @@ new FormModel {
name: "slider2"
"orientation": 1
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 7 6 1"
+ "value": "cell 1 7 7 1"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider3"
@@ -271,14 +288,14 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 7 6 1"
+ "value": "cell 1 7 7 1"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar2"
"orientation": 1
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 7 6 1"
+ "value": "cell 1 7 7 1"
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar4"
@@ -286,12 +303,12 @@ new FormModel {
"stringPainted": true
"value": 30
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 7 6 1"
+ "value": "cell 1 7 7 1"
} )
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
name: "hSpacer1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 7 6 1,growx"
+ "value": "cell 1 7 7 1,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label9"
@@ -306,7 +323,7 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 8 6 1"
+ "value": "cell 1 8 7 1"
} )
add( new FormComponent( "javax.swing.JSlider" ) {
name: "slider5"
@@ -316,12 +333,12 @@ new FormModel {
"majorTickSpacing": 25
"minorTickSpacing": 5
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 8 6 1"
+ "value": "cell 1 8 7 1"
} )
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
name: "hSpacer2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 1 8 6 1,growx"
+ "value": "cell 1 8 7 1,growx"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.java
index 18c5a0cb..5f4c5478 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.java
@@ -20,6 +20,7 @@ import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.BasicComboBoxEditor;
+import javax.swing.plaf.basic.BasicComboBoxRenderer;
import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*;
@@ -42,9 +43,23 @@ public class FlatCustomBordersTest
} );
}
+ @SuppressWarnings( "unchecked" )
FlatCustomBordersTest() {
initComponents();
applyCustomBorders();
+
+ DefaultComboBoxModel model = new DefaultComboBoxModel<>( new String[] {
+ "text",
+ "123",
+ "4567",
+ "abc",
+ "def"
+ } );
+
+ for( Component c : getComponents() ) {
+ if( c instanceof JComboBox )
+ ((JComboBox)c).setModel( model );
+ }
}
@Override
@@ -99,6 +114,13 @@ public class FlatCustomBordersTest
applyCustomComboBoxEditorBorderWithIcon( comboBox20 );
applyCustomComboBoxEditorBorder( comboBox21, 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 ) {
@@ -110,7 +132,7 @@ public class FlatCustomBordersTest
}
private void applyCustomComboBoxEditorBorder( JComboBox comboBox ) {
- applyCustomComboBoxEditorBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 3 ) ) );
+ applyCustomComboBoxEditorBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
}
private void applyCustomComboBoxEditorBorderWithIcon( JComboBox comboBox ) {
@@ -129,6 +151,21 @@ public class FlatCustomBordersTest
} );
}
+ private void applyCustomComboBoxRendererBorder( JComboBox comboBox ) {
+ applyCustomComboBoxRendererBorder( comboBox, new LineBorder( ORANGE, UIScale.scale( 6 ) ) );
+ }
+
+ private void applyCustomComboBoxRendererBorderWithIcon( JComboBox comboBox ) {
+ applyCustomComboBoxRendererBorder( comboBox, new BorderWithIcon() );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private void applyCustomComboBoxRendererBorder( JComboBox comboBox, Border border ) {
+ BasicComboBoxRenderer customRenderer = new BasicComboBoxRenderer();
+ customRenderer.setBorder( border );
+ comboBox.setRenderer( customRenderer );
+ }
+
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel();
@@ -152,10 +189,16 @@ public class FlatCustomBordersTest
comboBox2 = new JComboBox<>();
comboBox3 = new JComboBox<>();
comboBox4 = new JComboBox<>();
+ comboBox23 = new JComboBox<>();
+ comboBox25 = new JComboBox<>();
+ comboBox27 = new JComboBox<>();
comboBox5 = new JComboBox<>();
comboBox6 = new JComboBox<>();
comboBox7 = new JComboBox<>();
comboBox8 = new JComboBox<>();
+ comboBox24 = new JComboBox<>();
+ comboBox26 = new JComboBox<>();
+ comboBox28 = new JComboBox<>();
comboBox9 = new JComboBox<>();
comboBox10 = new JComboBox<>();
comboBox11 = new JComboBox<>();
@@ -289,6 +332,9 @@ public class FlatCustomBordersTest
add(comboBox2, "cell 2 3");
add(comboBox3, "cell 3 3");
add(comboBox4, "cell 4 3");
+ add(comboBox23, "cell 5 3");
+ add(comboBox25, "cell 6 3");
+ add(comboBox27, "cell 7 3");
//---- comboBox5 ----
comboBox5.putClientProperty("JComponent.roundRect", true);
@@ -306,6 +352,18 @@ public class FlatCustomBordersTest
comboBox8.putClientProperty("JComponent.roundRect", true);
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.setEditable(true);
add(comboBox9, "cell 1 5");
@@ -460,10 +518,16 @@ public class FlatCustomBordersTest
private JComboBox comboBox2;
private JComboBox comboBox3;
private JComboBox comboBox4;
+ private JComboBox comboBox23;
+ private JComboBox comboBox25;
+ private JComboBox comboBox27;
private JComboBox comboBox5;
private JComboBox comboBox6;
private JComboBox comboBox7;
private JComboBox comboBox8;
+ private JComboBox comboBox24;
+ private JComboBox comboBox26;
+ private JComboBox comboBox28;
private JComboBox comboBox9;
private JComboBox comboBox10;
private JComboBox comboBox11;
@@ -508,6 +572,9 @@ public class FlatCustomBordersTest
@Override
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) );
+
+ g.setColor( RED );
+ g.drawRect( x, y, width - 1, height - 1 );
}
@Override
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.jfd
index 36dea94b..6d67ea4a 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.jfd
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatCustomBordersTest.jfd
@@ -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 {
contentType: "form/swing"
@@ -147,6 +147,30 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"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" ) {
name: "comboBox5"
"$client.JComponent.roundRect": true
@@ -183,6 +207,33 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"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" ) {
name: "comboBox9"
"editable": true
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.java
index d0cb244f..c37f93fa 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.java
@@ -73,6 +73,25 @@ public class FlatPaintingTest
repaint();
}
+ private void offsetChanged() {
+ float offset = (float) offsetSpinner.getValue();
+ System.out.println( offset );
+
+ arrowPainter5.setYOffset( offset );
+ arrowPainter6.setYOffset( -offset );
+
+ arrowPainter7.setXOffset( offset );
+ arrowPainter8.setXOffset( -offset );
+
+ arrowPainter13.setYOffset( offset );
+ arrowPainter14.setYOffset( -offset );
+
+ arrowPainter15.setXOffset( offset );
+ arrowPainter16.setXOffset( -offset );
+
+ repaint();
+ }
+
private void vectorChanged() {
boolean vector = vectorCheckBox.isSelected();
@@ -84,7 +103,7 @@ public class FlatPaintingTest
repaint();
}
- private void checkBox1ActionPerformed() {
+ private void arrowButtonChanged() {
boolean button = buttonCheckBox.isSelected();
FlatTestFrame.updateComponentsRecur( (Container) getViewport().getView(), (c, type) -> {
@@ -143,11 +162,11 @@ public class FlatPaintingTest
FlatPaintingTest.ArrowPainter arrowPainter3 = new FlatPaintingTest.ArrowPainter();
FlatPaintingTest.ArrowPainter arrowPainter4 = new FlatPaintingTest.ArrowPainter();
JPanel panel1 = new JPanel();
- FlatPaintingTest.ArrowPainter arrowPainter5 = new FlatPaintingTest.ArrowPainter();
- FlatPaintingTest.ArrowPainter arrowPainter6 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter5 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter6 = new FlatPaintingTest.ArrowPainter();
JPanel panel2 = new JPanel();
- FlatPaintingTest.ArrowPainter arrowPainter7 = new FlatPaintingTest.ArrowPainter();
- FlatPaintingTest.ArrowPainter arrowPainter8 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter7 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter8 = new FlatPaintingTest.ArrowPainter();
JPanel panel5 = new JPanel();
JLabel arrowWidthLabel = new JLabel();
arrowWidthSpinner = new JSpinner();
@@ -155,6 +174,8 @@ public class FlatPaintingTest
arrowHeightSpinner = new JSpinner();
JLabel arrowSizeLabel = new JLabel();
arrowSizeSpinner = new JSpinner();
+ JLabel offsetLabel = new JLabel();
+ offsetSpinner = new JSpinner();
vectorCheckBox = new JCheckBox();
buttonCheckBox = new JCheckBox();
FlatPaintingTest.ArrowPainter arrowPainter9 = new FlatPaintingTest.ArrowPainter();
@@ -162,11 +183,11 @@ public class FlatPaintingTest
FlatPaintingTest.ArrowPainter arrowPainter11 = new FlatPaintingTest.ArrowPainter();
FlatPaintingTest.ArrowPainter arrowPainter12 = new FlatPaintingTest.ArrowPainter();
JPanel panel3 = new JPanel();
- FlatPaintingTest.ArrowPainter arrowPainter13 = new FlatPaintingTest.ArrowPainter();
- FlatPaintingTest.ArrowPainter arrowPainter14 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter13 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter14 = new FlatPaintingTest.ArrowPainter();
JPanel panel4 = new JPanel();
- FlatPaintingTest.ArrowPainter arrowPainter15 = new FlatPaintingTest.ArrowPainter();
- FlatPaintingTest.ArrowPainter arrowPainter16 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter15 = new FlatPaintingTest.ArrowPainter();
+ arrowPainter16 = new FlatPaintingTest.ArrowPainter();
//======== this ========
setBorder(null);
@@ -519,6 +540,7 @@ public class FlatPaintingTest
"[]" +
"[]" +
"[]" +
+ "[]" +
"[]"));
//---- arrowWidthLabel ----
@@ -548,17 +570,26 @@ public class FlatPaintingTest
arrowSizeSpinner.addChangeListener(e -> arrowSizeChanged());
panel5.add(arrowSizeSpinner, "cell 1 2");
+ //---- offsetLabel ----
+ offsetLabel.setText("Offset:");
+ panel5.add(offsetLabel, "cell 0 3");
+
+ //---- offsetSpinner ----
+ offsetSpinner.setModel(new SpinnerNumberModel(1.0F, null, null, 0.05F));
+ offsetSpinner.addChangeListener(e -> offsetChanged());
+ panel5.add(offsetSpinner, "cell 1 3");
+
//---- vectorCheckBox ----
vectorCheckBox.setText("vector");
vectorCheckBox.addActionListener(e -> vectorChanged());
- panel5.add(vectorCheckBox, "cell 0 3 2 1,alignx left,growx 0");
+ panel5.add(vectorCheckBox, "cell 0 4 2 1,alignx left,growx 0");
//---- buttonCheckBox ----
buttonCheckBox.setText("FlatArrowButton");
- buttonCheckBox.addActionListener(e -> checkBox1ActionPerformed());
- panel5.add(buttonCheckBox, "cell 0 4 2 1,alignx left,growx 0");
+ buttonCheckBox.addActionListener(e -> arrowButtonChanged());
+ panel5.add(buttonCheckBox, "cell 0 5 2 1,alignx left,growx 0");
}
- flatTestPanel1.add(panel5, "cell 6 5,aligny top,growy 0");
+ flatTestPanel1.add(panel5, "cell 6 5 1 2,aligny top,growy 0");
//---- arrowPainter9 ----
arrowPainter9.setScale(8.0F);
@@ -635,11 +666,20 @@ public class FlatPaintingTest
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
+ private FlatPaintingTest.ArrowPainter arrowPainter5;
+ private FlatPaintingTest.ArrowPainter arrowPainter6;
+ private FlatPaintingTest.ArrowPainter arrowPainter7;
+ private FlatPaintingTest.ArrowPainter arrowPainter8;
private JSpinner arrowWidthSpinner;
private JSpinner arrowHeightSpinner;
private JSpinner arrowSizeSpinner;
+ private JSpinner offsetSpinner;
private JCheckBox vectorCheckBox;
private JCheckBox buttonCheckBox;
+ private FlatPaintingTest.ArrowPainter arrowPainter13;
+ private FlatPaintingTest.ArrowPainter arrowPainter14;
+ private FlatPaintingTest.ArrowPainter arrowPainter15;
+ private FlatPaintingTest.ArrowPainter arrowPainter16;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class BorderPainter ------------------------------------------------
@@ -792,8 +832,8 @@ public class FlatPaintingTest
private int direction = SwingConstants.SOUTH;
private boolean chevron = true;
private int arrowSize = FlatArrowButton.DEFAULT_ARROW_WIDTH;
- private int xOffset = 0;
- private int yOffset = 0;
+ private float xOffset = 0;
+ private float yOffset = 0;
private float scale = 1;
private boolean halfWidth;
private boolean halfHeight;
@@ -845,19 +885,19 @@ public class FlatPaintingTest
this.arrowSize = arrowSize;
}
- public int getXOffset() {
+ public float getXOffset() {
return xOffset;
}
- public void setXOffset( int xOffset ) {
+ public void setXOffset( float xOffset ) {
this.xOffset = xOffset;
}
- public int getYOffset() {
+ public float getYOffset() {
return yOffset;
}
- public void setYOffset( int yOffset ) {
+ public void setYOffset( float yOffset ) {
this.yOffset = yOffset;
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.jfd
index 0d6c21c2..bd77fa17 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.jfd
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatPaintingTest.jfd
@@ -1,4 +1,4 @@
-JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
+JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -383,6 +383,9 @@ new FormModel {
"h": 10
"halfHeight": true
"YOffset": 1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingTest$ArrowPainter" ) {
name: "arrowPainter6"
@@ -390,6 +393,9 @@ new FormModel {
"h": 10
"halfHeight": true
"YOffset": -1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 5,align left top,grow 0 0"
@@ -403,6 +409,9 @@ new FormModel {
"w": 10
"halfWidth": true
"XOffset": 1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingTest$ArrowPainter" ) {
name: "arrowPainter8"
@@ -411,6 +420,9 @@ new FormModel {
"w": 10
"halfWidth": true
"XOffset": -1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 5,align left top,grow 0 0"
@@ -418,7 +430,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill][fill]"
- "$rowConstraints": "[][][][][]"
+ "$rowConstraints": "[][][][][][]"
} ) {
name: "panel5"
"border": new javax.swing.border.TitledBorder( "Arrow Control" )
@@ -479,6 +491,25 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "offsetLabel"
+ "text": "Offset:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 3"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "offsetSpinner"
+ "model": new javax.swing.SpinnerNumberModel {
+ stepSize: 0.05f
+ value: 1.0f
+ }
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "offsetChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 3"
+ } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "vectorCheckBox"
"text": "vector"
@@ -487,7 +518,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "vectorChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 0 3 2 1,alignx left,growx 0"
+ "value": "cell 0 4 2 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "buttonCheckBox"
@@ -495,12 +526,12 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
- addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "checkBox1ActionPerformed", false ) )
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "arrowButtonChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 0 4 2 1,alignx left,growx 0"
+ "value": "cell 0 5 2 1,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 6 5,aligny top,growy 0"
+ "value": "cell 6 5 1 2,aligny top,growy 0"
} )
add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingTest$ArrowPainter" ) {
name: "arrowPainter9"
@@ -545,6 +576,9 @@ new FormModel {
"chevron": false
"halfHeight": true
"YOffset": 1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingTest$ArrowPainter" ) {
name: "arrowPainter14"
@@ -553,6 +587,9 @@ new FormModel {
"chevron": false
"halfHeight": true
"YOffset": -1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 6,align left top,grow 0 0"
@@ -567,6 +604,9 @@ new FormModel {
"chevron": false
"halfWidth": true
"XOffset": 1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
add( new FormComponent( "com.formdev.flatlaf.testing.FlatPaintingTest$ArrowPainter" ) {
name: "arrowPainter16"
@@ -576,6 +616,9 @@ new FormModel {
"chevron": false
"halfWidth": true
"XOffset": -1
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 6,align left top,grow 0 0"
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java
index 1d5cb38a..07d3e630 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java
@@ -23,6 +23,7 @@ import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -284,6 +285,8 @@ public class FlatTestFrame
Properties properties = new Properties();
try( InputStream in = new FileInputStream( "lafs.properties" ) ) {
properties.load( in );
+ } catch( FileNotFoundException ex ) {
+ // ignore
} catch( IOException ex ) {
ex.printStackTrace();
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java
index 80b68989..ecb55f42 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java
@@ -16,8 +16,12 @@
package com.formdev.flatlaf.testing;
+import java.awt.Component;
+import java.awt.Insets;
import javax.swing.*;
+import javax.swing.border.*;
import javax.swing.text.DefaultEditorKit;
+import com.formdev.flatlaf.FlatClientProperties;
import net.miginfocom.swing.*;
/**
@@ -41,16 +45,40 @@ public class FlatTextComponentsTest
textField1.setText( "new text" );
}
+ private void paddingChanged() {
+ Insets padding = new Insets(
+ (int) topPaddingField.getValue(),
+ (int) leftPaddingField.getValue(),
+ (int) bottomPaddingField.getValue(),
+ (int) rightPaddingField.getValue() );
+ if( padding.equals( new Insets( 0, 0, 0, 0 ) ) )
+ padding = null;
+
+ for( Component c : getComponents() ) {
+ if( c instanceof JTextField )
+ ((JTextField)c).putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding );
+ }
+ }
+
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel textFieldLabel = new JLabel();
textField1 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField2 = new JTextField();
- JButton button1 = new JButton();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
+ JPanel panel1 = new JPanel();
+ JButton button1 = new JButton();
+ JLabel leftPaddingLabel = new JLabel();
+ leftPaddingField = new JSpinner();
+ JLabel rightPaddingLabel = new JLabel();
+ rightPaddingField = new JSpinner();
+ JLabel topPaddingLabel = new JLabel();
+ topPaddingField = new JSpinner();
+ JLabel bottomPaddingLabel = new JLabel();
+ bottomPaddingField = new JSpinner();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
@@ -134,12 +162,6 @@ public class FlatTextComponentsTest
textField2.setName("textField2");
add(textField2, "cell 3 0");
- //---- button1 ----
- button1.setText("change text");
- button1.setName("button1");
- button1.addActionListener(e -> changeText());
- add(button1, "cell 4 0");
-
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
formattedTextFieldLabel.setDisplayedMnemonic('F');
@@ -159,6 +181,70 @@ public class FlatTextComponentsTest
formattedTextField3.setName("formattedTextField3");
add(formattedTextField3, "cell 2 1,growx");
+ //======== panel1 ========
+ {
+ panel1.setBorder(new TitledBorder("Control"));
+ panel1.setName("panel1");
+ panel1.setLayout(new MigLayout(
+ "hidemode 3",
+ // columns
+ "[fill]" +
+ "[fill]",
+ // rows
+ "[]" +
+ "[]" +
+ "[]" +
+ "[]" +
+ "[]"));
+
+ //---- button1 ----
+ button1.setText("change text");
+ button1.setName("button1");
+ button1.addActionListener(e -> changeText());
+ panel1.add(button1, "cell 0 0 2 1,alignx left,growx 0");
+
+ //---- leftPaddingLabel ----
+ leftPaddingLabel.setText("Left padding:");
+ leftPaddingLabel.setName("leftPaddingLabel");
+ panel1.add(leftPaddingLabel, "cell 0 1");
+
+ //---- leftPaddingField ----
+ leftPaddingField.setName("leftPaddingField");
+ leftPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(leftPaddingField, "cell 1 1");
+
+ //---- rightPaddingLabel ----
+ rightPaddingLabel.setText("Right padding:");
+ rightPaddingLabel.setName("rightPaddingLabel");
+ panel1.add(rightPaddingLabel, "cell 0 2");
+
+ //---- rightPaddingField ----
+ rightPaddingField.setName("rightPaddingField");
+ rightPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(rightPaddingField, "cell 1 2");
+
+ //---- topPaddingLabel ----
+ topPaddingLabel.setText("Top padding:");
+ topPaddingLabel.setName("topPaddingLabel");
+ panel1.add(topPaddingLabel, "cell 0 3");
+
+ //---- topPaddingField ----
+ topPaddingField.setName("topPaddingField");
+ topPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(topPaddingField, "cell 1 3");
+
+ //---- bottomPaddingLabel ----
+ bottomPaddingLabel.setText("Bottom padding:");
+ bottomPaddingLabel.setName("bottomPaddingLabel");
+ panel1.add(bottomPaddingLabel, "cell 0 4");
+
+ //---- bottomPaddingField ----
+ bottomPaddingField.setName("bottomPaddingField");
+ bottomPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(bottomPaddingField, "cell 1 4");
+ }
+ add(panel1, "cell 4 0 1 6,aligny top,growy 0");
+
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
passwordFieldLabel.setDisplayedMnemonic('P');
@@ -301,7 +387,7 @@ public class FlatTextComponentsTest
comboBox3.setPrototypeDisplayValue("12345");
comboBox3.setComponentPopupMenu(popupMenu1);
comboBox3.setName("comboBox3");
- add(comboBox3, "cell 2 6,growx");
+ add(comboBox3, "cell 2 6,growx,wmin 50");
//---- spinnerLabel ----
spinnerLabel.setText("JSpinner:");
@@ -361,5 +447,9 @@ public class FlatTextComponentsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JTextField textField1;
+ private JSpinner leftPaddingField;
+ private JSpinner rightPaddingField;
+ private JSpinner topPaddingField;
+ private JSpinner bottomPaddingField;
// JFormDesigner - End of variables declaration //GEN-END:variables
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd
index aa4526b3..b8bcac13 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd
@@ -1,4 +1,4 @@
-JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
+JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -47,13 +47,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 0"
} )
- add( new FormComponent( "javax.swing.JButton" ) {
- name: "button1"
- "text": "change text"
- addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeText", false ) )
- }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 4 0"
- } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -76,6 +69,83 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1,growx"
} )
+ add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
+ "$layoutConstraints": "hidemode 3"
+ "$columnConstraints": "[fill][fill]"
+ "$rowConstraints": "[][][][][]"
+ } ) {
+ name: "panel1"
+ "border": new javax.swing.border.TitledBorder( "Control" )
+ add( new FormComponent( "javax.swing.JButton" ) {
+ name: "button1"
+ "text": "change text"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeText", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 0 2 1,alignx left,growx 0"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "leftPaddingLabel"
+ "text": "Left padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 1"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "leftPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 1"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "rightPaddingLabel"
+ "text": "Right padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 2"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "rightPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 2"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "topPaddingLabel"
+ "text": "Top padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 3"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "topPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 3"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "bottomPaddingLabel"
+ "text": "Bottom padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 4"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "bottomPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4"
+ } )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 4 0 1 6,aligny top,growy 0"
+ } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -217,7 +287,7 @@ new FormModel {
"prototypeDisplayValue": "12345"
"componentPopupMenu": #FormReference0
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 2 6,growx"
+ "value": "cell 2 6,growx,wmin 50"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "spinnerLabel"
diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties
index cc4d76a7..589e78dd 100644
--- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties
+++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties
@@ -132,7 +132,7 @@ ComboBox.buttonEditableBackground = #ccc
ComboBox.focusedBackground = #ff8
ComboBox.buttonFocusedBackground = #ff0
-ComboBox.popupFocusedBackground = #ffc
+ComboBox.popupBackground = #ffc
#---- Component ----