From 4cdc995a7f40eaa572ac1e8848c50c6113cc4936 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 5 Jul 2021 23:14:05 +0200 Subject: [PATCH 01/16] ComboBox: simplified code in configureEditor() --- .../java/com/formdev/flatlaf/ui/FlatComboBoxUI.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) 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 840a57bf..5d84415b 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 @@ -356,13 +356,9 @@ public class FlatComboBoxUI protected void configureEditor() { super.configureEditor(); - if( editor instanceof JTextField ) { - JTextField textField = (JTextField) editor; - - // remove default text field border from editor - if( textField.getBorder() instanceof FlatTextBorder ) - textField.setBorder( BorderFactory.createEmptyBorder() ); - } + // remove default text field border from editor + if( editor instanceof JTextField && ((JTextField)editor).getBorder() instanceof FlatTextBorder ) + ((JTextField)editor).setBorder( BorderFactory.createEmptyBorder() ); // explicitly make non-opaque if( editor instanceof JComponent ) @@ -554,7 +550,6 @@ public class FlatComboBoxUI @Override protected Dimension getDisplaySize() { - paddingBorder.uninstall(); Dimension displaySize = super.getDisplaySize(); paddingBorder.uninstall(); From a28f701e6f26ee54f88233da8b60047592077476 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 7 Jul 2021 10:57:54 +0200 Subject: [PATCH 02/16] OptionPane: do not make child components, which are derived from `JPanel`, non-opaque (issue #349) --- CHANGELOG.md | 2 ++ .../main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1050dcf2..e913ef5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ FlatLaf Change Log components by: - `2px` at `1.75x` in **Light** and **Dark** themes - `2px` at `1.25x` and `2.25x` in **IntelliJ** and **Darcula** themes +- OptionPane: Do not make child components, which are derived from `JPanel`, + non-opaque. (issue #349) ## 1.3 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java index b8e7bb20..f7632e33 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java @@ -165,7 +165,7 @@ public class FlatOptionPaneUI private void updateChildPanels( Container c ) { for( Component child : c.getComponents() ) { - if( child instanceof JPanel ) { + if( child.getClass() == JPanel.class ) { JPanel panel = (JPanel)child; // make sub-panel non-opaque for OptionPane.background @@ -177,9 +177,8 @@ public class FlatOptionPaneUI panel.setBorder( new NonUIResourceBorder( border ) ); } - if( child instanceof Container ) { + if( child instanceof Container ) updateChildPanels( (Container) child ); - } } } From abbe6d6c1fd09b1ca432c4002589152e8cab1be5 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 7 Jul 2021 18:16:45 +0200 Subject: [PATCH 03/16] ToolBar: paint focus indicator for focused button in toolbar (issue #346) --- CHANGELOG.md | 1 + .../formdev/flatlaf/ui/FlatButtonBorder.java | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e913ef5d..e4ec4101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ FlatLaf Change Log - PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI` (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier extensibility. +- ToolBar: Paint focus indicator for focused button in toolbar. (issue #346) #### Fixed bugs diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java index 7d3e06a3..d813c4b6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java @@ -20,6 +20,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.GradientPaint; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Paint; import javax.swing.AbstractButton; @@ -42,11 +43,13 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault Button.default.hoverBorderColor Color optional * @uiDefault Button.default.focusedBorderColor Color * @uiDefault Button.default.focusColor Color + * @uiDefault Button.toolbar.focusColor Color optional; defaults to Component.focusColor * @uiDefault Button.borderWidth int * @uiDefault Button.default.borderWidth int * @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth * @uiDefault Button.toolbar.margin Insets * @uiDefault Button.toolbar.spacingInsets Insets + * @uiDefault Button.toolbar.focusWidth int or float optional; default is 1 * @uiDefault Button.arc int * * @author Karl Tauber @@ -64,11 +67,15 @@ public class FlatButtonBorder protected final Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" ); protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" ); protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" ); + /** @since 1.4 */ + protected final Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" ); protected final int borderWidth = UIManager.getInt( "Button.borderWidth" ); protected final int defaultBorderWidth = UIManager.getInt( "Button.default.borderWidth" ); protected final float buttonInnerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth ); protected final Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" ); protected final Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" ); + /** @since 1.4 */ + protected final float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f ); protected final int arc = UIManager.getInt( "Button.arc" ); @Override @@ -79,11 +86,41 @@ public class FlatButtonBorder !FlatButtonUI.isHelpButton( c ) && !FlatToggleButtonUI.isTabButton( c ) ) super.paintBorder( c, g, x, y, width, height ); + else if( FlatButtonUI.isToolBarButton( c ) && isFocused( c ) ) + paintToolBarFocus( c, g, x, y, width, height ); + } + + /** + * @since 1.4 + */ + protected void paintToolBarFocus( Component c, Graphics g, int x, int y, int width, int height ) { + Graphics2D g2 = (Graphics2D) g.create(); + try { + FlatUIUtils.setRenderingHints( g2 ); + + float focusWidth = UIScale.scale( toolbarFocusWidth ); + float arc = UIScale.scale( (float) getArc( c ) ); + Color outlineColor = getOutlineColor( c ); + + Insets spacing = UIScale.scale( toolbarSpacingInsets ); + x += spacing.left; + y += spacing.top; + width -= spacing.left + spacing.right; + height -= spacing.top + spacing.bottom; + + g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) ); + // not using paintComponentOuterBorder() here because its round edges look too "thick" + FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0, focusWidth, arc ); + } finally { + g2.dispose(); + } } @Override protected Color getFocusColor( Component c ) { - return FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c ); + return (toolbarFocusColor != null && FlatButtonUI.isToolBarButton( c )) + ? toolbarFocusColor + : (FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c )); } @Override From 90282d44369f45e270984c1a97d172349991dadb Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 8 Jul 2021 00:02:33 +0200 Subject: [PATCH 04/16] UI defaults dumps updated for issue #335 --- .../dumps/uidefaults/FlatTestLaf_1.8.0_202.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt index 0ab6c35f..62a7b049 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt @@ -194,6 +194,7 @@ ComboBox.buttonBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonDarkShadow #696969 javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonDisabledArrowColor #ababab javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonEditableBackground #cccccc javax.swing.plaf.ColorUIResource [UI] +ComboBox.buttonFocusedBackground #ffff00 javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonHighlight #ffffff javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonHoverArrowColor #ff0000 javax.swing.plaf.ColorUIResource [UI] ComboBox.buttonPressedArrowColor #0000ff javax.swing.plaf.ColorUIResource [UI] @@ -202,6 +203,7 @@ ComboBox.buttonStyle auto ComboBox.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] ComboBox.disabledForeground #000088 javax.swing.plaf.ColorUIResource [UI] ComboBox.editorColumns 0 +ComboBox.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] ComboBox.font [active] $defaultFont [UI] ComboBox.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] ComboBox.isEnterSelectablePopup false @@ -209,6 +211,7 @@ ComboBox.maximumRowCount 15 ComboBox.minimumWidth 72 ComboBox.noActionOnKeyNavigation false ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] +ComboBox.popupBackground #ffffcc javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #00aa00 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #ffff00 javax.swing.plaf.ColorUIResource [UI] ComboBox.timeFactor 1000 @@ -265,6 +268,7 @@ EditorPane.border [lazy] 0,0,0,0 false com.formdev.flatlaf.ui.F EditorPane.caretBlinkRate 500 EditorPane.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] EditorPane.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] +EditorPane.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] EditorPane.font [active] $defaultFont [UI] EditorPane.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] EditorPane.inactiveBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] @@ -304,6 +308,7 @@ FormattedTextField.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.F FormattedTextField.caretBlinkRate 500 FormattedTextField.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] FormattedTextField.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] +FormattedTextField.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] FormattedTextField.font [active] $defaultFont [UI] FormattedTextField.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] FormattedTextField.inactiveBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] @@ -700,6 +705,7 @@ PasswordField.caretBlinkRate 500 PasswordField.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] PasswordField.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] PasswordField.echoChar '\u2022' +PasswordField.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] PasswordField.font [active] $defaultFont [UI] PasswordField.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] PasswordField.inactiveBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] @@ -935,6 +941,7 @@ Spinner.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] Spinner.disabledForeground #000088 javax.swing.plaf.ColorUIResource [UI] Spinner.editorAlignment 11 Spinner.editorBorderPainted false +Spinner.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] Spinner.font [active] $defaultFont [UI] Spinner.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] Spinner.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] @@ -1111,6 +1118,7 @@ TextArea.border [lazy] 0,0,0,0 false com.formdev.flatlaf.ui.F TextArea.caretBlinkRate 500 TextArea.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] TextArea.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] +TextArea.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] TextArea.font [active] $defaultFont [UI] TextArea.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] TextArea.inactiveBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] @@ -1136,6 +1144,7 @@ TextField.caretBlinkRate 500 TextField.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] TextField.darkShadow #696969 javax.swing.plaf.ColorUIResource [UI] TextField.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] +TextField.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] TextField.font [active] $defaultFont [UI] TextField.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] TextField.highlight #ffffff javax.swing.plaf.ColorUIResource [UI] @@ -1157,6 +1166,7 @@ TextPane.border [lazy] 0,0,0,0 false com.formdev.flatlaf.ui.F TextPane.caretBlinkRate 500 TextPane.caretForeground #0000ff javax.swing.plaf.ColorUIResource [UI] TextPane.disabledBackground #e0e0e0 javax.swing.plaf.ColorUIResource [UI] +TextPane.focusedBackground #ffff88 javax.swing.plaf.ColorUIResource [UI] TextPane.font [active] $defaultFont [UI] TextPane.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] TextPane.inactiveBackground #f0f0f0 javax.swing.plaf.ColorUIResource [UI] From 87407ca8320a9c272ca8271150798533ca56edd0 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 8 Jul 2021 14:02:50 +0200 Subject: [PATCH 05/16] Table and PopupFactory: use `StackWalker` in Java 9+ for better performance (issue #334) --- CHANGELOG.md | 2 + .../formdev/flatlaf/ui/FlatPopupFactory.java | 9 +--- .../com/formdev/flatlaf/ui/FlatTableUI.java | 18 +------ .../com/formdev/flatlaf/ui/StackUtils.java | 50 +++++++++++++++++++ .../formdev/flatlaf/ui/StackUtilsImpl.java | 41 +++++++++++++++ .../formdev/flatlaf/ui/StackUtilsImpl.java | 37 ++++++++++++++ 6 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtils.java create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtilsImpl.java create mode 100644 flatlaf-core/src/main/java9/com/formdev/flatlaf/ui/StackUtilsImpl.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e4ec4101..47a82870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ FlatLaf Change Log - PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI` (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier extensibility. +- Table and PopupFactory: Use `StackWalker` in Java 9+ for better performance. + (issue #334) - ToolBar: Paint focus indicator for focused button in toolbar. (issue #346) #### Fixed bugs diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java index 061d9e0a..374e5e6a 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java @@ -44,6 +44,7 @@ import javax.swing.Popup; import javax.swing.PopupFactory; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; +import javax.swing.ToolTipManager; import javax.swing.UIManager; import javax.swing.border.Border; import com.formdev.flatlaf.FlatClientProperties; @@ -260,13 +261,7 @@ public class FlatPopupFactory } private boolean wasInvokedFromToolTipManager() { - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for( StackTraceElement stackTraceElement : stackTrace ) { - if( "javax.swing.ToolTipManager".equals( stackTraceElement.getClassName() ) && - "showTipWindow".equals( stackTraceElement.getMethodName() ) ) - return true; - } - return false; + return StackUtils.wasInvokedFrom( ToolTipManager.class.getName(), "showTipWindow", 8 ); } //---- class NonFlashingPopup --------------------------------------------- diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java index 84e4edfa..11ad7154 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java @@ -240,7 +240,7 @@ public class FlatTableUI if( isDragging && SystemInfo.isJava_9_orLater && ((horizontalLines && y1 == y2) || (verticalLines && x1 == x2)) && - wasInvokedFromPaintDraggedArea() ) + wasInvokedFromMethod( "paintDraggedArea" ) ) { if( y1 == y2 ) { // horizontal grid line @@ -282,22 +282,8 @@ public class FlatTableUI return wasInvokedFromMethod( "paintGrid" ); } - private boolean wasInvokedFromPaintDraggedArea() { - return wasInvokedFromMethod( "paintDraggedArea" ); - } - private boolean wasInvokedFromMethod( String methodName ) { - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for( int i = 0; i < 10 || i < stackTrace.length; i++ ) { - if( "javax.swing.plaf.basic.BasicTableUI".equals( stackTrace[i].getClassName() ) ) { - String methodName2 = stackTrace[i].getMethodName(); - if( "paintCell".equals( methodName2 ) ) - return false; - if( methodName.equals( methodName2 ) ) - return true; - } - } - return false; + return StackUtils.wasInvokedFrom( BasicTableUI.class.getName(), methodName, 8 ); } }; } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtils.java new file mode 100644 index 00000000..0d833689 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtils.java @@ -0,0 +1,50 @@ +/* + * 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.util.function.BiPredicate; + +/** + * @author Karl Tauber + */ +class StackUtils +{ + private static final StackUtils INSTANCE = new StackUtilsImpl(); + + // hide from javadoc + StackUtils() { + } + + /** + * Checks whether current method was invoked from the given class and method. + */ + public static boolean wasInvokedFrom( String className, String methodName, int limit ) { + return wasInvokedFrom( (c,m) -> c.equals( className ) && m.equals( methodName ), limit ); + } + + /** + * Checks whether current method was invoked from a class and method using the given predicate, + * which gets the class name of the stack frame as first parameter and the method name as second parameter. + */ + public static boolean wasInvokedFrom( BiPredicate predicate, int limit ) { + return INSTANCE.wasInvokedFromImpl( predicate, limit ); + } + + boolean wasInvokedFromImpl( BiPredicate predicate, int limit ) { + throw new UnsupportedOperationException(); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtilsImpl.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtilsImpl.java new file mode 100644 index 00000000..0775c413 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/StackUtilsImpl.java @@ -0,0 +1,41 @@ +/* + * 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.util.function.BiPredicate; + +/** + * @author Karl Tauber + */ +class StackUtilsImpl + extends StackUtils +{ + @Override + boolean wasInvokedFromImpl( BiPredicate predicate, int limit ) { + int count = -2; + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + for( StackTraceElement stackTraceElement : stackTrace ) { + if( predicate.test( stackTraceElement.getClassName(), stackTraceElement.getMethodName() ) ) + return true; + + count++; + if( limit > 0 && count > limit ) + return false; + } + return false; + } +} diff --git a/flatlaf-core/src/main/java9/com/formdev/flatlaf/ui/StackUtilsImpl.java b/flatlaf-core/src/main/java9/com/formdev/flatlaf/ui/StackUtilsImpl.java new file mode 100644 index 00000000..0ba0fcc2 --- /dev/null +++ b/flatlaf-core/src/main/java9/com/formdev/flatlaf/ui/StackUtilsImpl.java @@ -0,0 +1,37 @@ +/* + * 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.util.function.BiPredicate; + +/** + * @author Karl Tauber + */ +class StackUtilsImpl + extends StackUtils +{ + @Override + boolean wasInvokedFromImpl( BiPredicate predicate, int limit ) { + return StackWalker.getInstance().walk( stream -> { + if( limit > 0 ) + stream = stream.limit( limit + 2 ); + return stream.anyMatch( f -> { + return predicate.test( f.getClassName(), f.getMethodName() ); + } ); + } ); + } +} From 266a546478e6db93af1b803add4bcbe64bc98e7d Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 8 Jul 2021 16:54:34 +0200 Subject: [PATCH 06/16] Window decorations: window title bar width is no longer considered when calculating preferred/minimum width of window (issue #351) --- CHANGELOG.md | 2 ++ .../src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a82870..4ac0ca56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,8 @@ FlatLaf Change Log - `2px` at `1.25x` and `2.25x` in **IntelliJ** and **Darcula** themes - OptionPane: Do not make child components, which are derived from `JPanel`, non-opaque. (issue #349) +- Window decorations: Window title bar width is no longer considered when + calculating preferred/minimum width of window. (issue #351) ## 1.3 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java index 185e32c0..35d50741 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java @@ -342,7 +342,7 @@ public class FlatRootPaneUI ? getSizeFunc.apply( rootPane.getContentPane() ) : rootPane.getSize(); - int width = Math.max( titlePaneSize.width, contentSize.width ); + int width = contentSize.width; // title pane width is not considered here int height = titlePaneSize.height + contentSize.height; if( titlePane == null || !titlePane.isMenuBarEmbedded() ) { JMenuBar menuBar = rootPane.getJMenuBar(); From ff9ef21f67dfa96abf97ad27c3c1d1f57798c083 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 8 Jul 2021 17:53:44 +0200 Subject: [PATCH 07/16] OptionPane: align wrapped lines to the right if component orientation is right-to-left (issue #350) --- CHANGELOG.md | 2 + .../formdev/flatlaf/ui/FlatOptionPaneUI.java | 21 ++++++++++ .../flatlaf/testing/FlatOptionPaneTest.java | 38 ++++++++++++++++++- .../flatlaf/testing/FlatOptionPaneTest.jfd | 36 ++++++++++++++++-- 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ac0ca56..25f254a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,8 @@ FlatLaf Change Log - `2px` at `1.25x` and `2.25x` in **IntelliJ** and **Darcula** themes - OptionPane: Do not make child components, which are derived from `JPanel`, non-opaque. (issue #349) +- OptionPane: Align wrapped lines to the right if component orientation is + right-to-left. (issue #350) - Window decorations: Window title bar width is no longer considered when calculating preferred/minimum width of window. (issue #351) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java index f7632e33..7475ce9b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java @@ -22,7 +22,10 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.Insets; +import javax.swing.Box; +import javax.swing.BoxLayout; import javax.swing.JComponent; +import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.border.Border; @@ -160,6 +163,24 @@ public class FlatOptionPaneUI if( msg instanceof String && BasicHTML.isHTMLString( (String) msg ) ) maxll = Integer.MAX_VALUE; + // fix right-to-left alignment if super.addMessageComponents() breaks longer lines + // into multiple labels and puts them into a box that aligns them to the left + if( msg instanceof Box ) { + Box box = (Box) msg; + if( "OptionPane.verticalBox".equals( box.getName() ) && + box.getLayout() instanceof BoxLayout && + ((BoxLayout)box.getLayout()).getAxis() == BoxLayout.Y_AXIS ) + { + box.addPropertyChangeListener( "componentOrientation", e -> { + float alignX = box.getComponentOrientation().isLeftToRight() ? 0 : 1; + for( Component c : box.getComponents() ) { + if( c instanceof JLabel && "OptionPane.label".equals( c.getName() ) ) + ((JLabel)c).setAlignmentX( alignX ); + } + } ); + } + } + super.addMessageComponents( container, cons, msg, maxll, internallyCreated ); } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java index 38b90638..3c3cda88 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java @@ -89,6 +89,10 @@ public class FlatOptionPaneTest JPanel panel6 = new JPanel(); customOptionPane = new JOptionPane(); FlatOptionPaneTest.ShowDialogLinkLabel customShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel(); + JLabel rightToLeftLabel = new JLabel(); + JPanel panel10 = new JPanel(); + JOptionPane rightToLeftOptionPane = new JOptionPane(); + rightToLeftShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel(); //======== this ======== setBorder(BorderFactory.createEmptyBorder()); @@ -109,6 +113,7 @@ public class FlatOptionPaneTest "[top]" + "[top]" + "[top]" + + "[top]" + "[top]")); //---- plainLabel ---- @@ -283,6 +288,28 @@ public class FlatOptionPaneTest customShowDialogLabel.setOptionPane(customOptionPane); customShowDialogLabel.setTitleLabel(customLabel); panel9.add(customShowDialogLabel, "cell 2 7"); + + //---- rightToLeftLabel ---- + rightToLeftLabel.setText("Right-to-left:"); + panel9.add(rightToLeftLabel, "cell 0 8"); + + //======== panel10 ======== + { + panel10.setBorder(LineBorder.createGrayLineBorder()); + panel10.setLayout(new BorderLayout()); + + //---- rightToLeftOptionPane ---- + rightToLeftOptionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); + rightToLeftOptionPane.setMessage("\u0627\u0644\u0645\u0627\u062f\u0629 1 \u064a\u0648\u0644\u062f \u062c\u0645\u064a\u0639 \u0627\u0644\u0646\u0627\u0633 \u0623\u062d\u0631\u0627\u0631\u064b\u0627 \u0645\u062a\u0633\u0627\u0648\u064a\u0646 \u0641\u064a \u0627\u0644\u0643\u0631\u0627\u0645\u0629 \u0648\u0627\u0644\u062d\u0642\u0648\u0642. \u0648\u0642\u062f \u0648\u0647\u0628\u0648\u0627 \u0639\u0642\u0644\u0627\u064b \u0648\u0636\u0645\u064a\u0631\u064b\u0627 \u0648\u0639\u0644\u064a\u0647\u0645 \u0623\u0646 \u064a\u0639\u0627\u0645\u0644 \u0628\u0639\u0636\u0647\u0645 \u0628\u0639\u0636\u064b\u0627 \u0628\u0631\u0648\u062d \u0627\u0644\u0625\u062e\u0627\u0621.\n\u0627\u0644\u0645\u0627\u062f\u0629 1 \u064a\u0648\u0644\u062f \u062c\u0645\u064a\u0639 \u0627\u0644\u0646\u0627\u0633 \u0623\u062d\u0631\u0627\u0631\u064b\u0627 \u0645\u062a\u0633\u0627\u0648\u064a\u0646 \u0641\u064a \u0627\u0644\u0643\u0631\u0627\u0645\u0629 \u0648\u0627\u0644\u062d\u0642\u0648\u0642. \u0648\u0642\u062f \u0648\u0647\u0628\u0648\u0627 \u0639\u0642\u0644\u0627\u064b \u0648\u0636\u0645\u064a\u0631\u064b\u0627 \u0648\u0639\u0644\u064a\u0647\u0645 \u0623\u0646 \u064a\u0639\u0627\u0645\u0644 \u0628\u0639\u0636\u0647\u0645 \u0628\u0639\u0636\u064b\u0627 \u0628\u0631\u0648\u062d \u0627\u0644\u0625\u062e\u0627\u0621.\n\n\u0627\u0644\u0645\u0627\u062f\u0629 1 \u064a\u0648\u0644\u062f \u062c\u0645\u064a\u0639 \u0627\u0644\u0646\u0627\u0633 \u0623\u062d\u0631\u0627\u0631\u064b\u0627 \u0645\u062a\u0633\u0627\u0648\u064a\u0646 \u0641\u064a \u0627\u0644\u0643\u0631\u0627\u0645\u0629 \n\u0648\u0627\u0644\u062d\u0642\u0648\u0642. \u0648\u0642\u062f \u0648\u0647\u0628\u0648\u0627 \u0639\u0642\u0644\u0627\u064b \u0648\u0636\u0645\u064a\u0631\u064b\u0627 \u0648\u0639\u0644\u064a\u0647\u0645 \u0623\u0646 \u064a\u0639\u0627\u0645\u0644 \u0628\u0639\u0636\u0647\u0645 \u0628\u0639\u0636\u064b\u0627 \u0628\u0631\u0648\u062d \u0627\u0644\u0625\u062e\u0627\u0621."); + rightToLeftOptionPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + panel10.add(rightToLeftOptionPane, BorderLayout.CENTER); + } + panel9.add(panel10, "cell 1 8"); + + //---- rightToLeftShowDialogLabel ---- + rightToLeftShowDialogLabel.setOptionPane(rightToLeftOptionPane); + rightToLeftShowDialogLabel.setTitleLabel(rightToLeftLabel); + panel9.add(rightToLeftShowDialogLabel, "cell 2 8"); } setViewportView(panel9); // JFormDesigner - End of component initialization //GEN-END:initComponents @@ -293,6 +320,7 @@ public class FlatOptionPaneTest private FlatOptionPaneTest.ShowDialogLinkLabel errorShowDialogLabel; private FlatOptionPaneTest.ShowDialogLinkLabel informationShowDialogLabel; private JOptionPane customOptionPane; + private FlatOptionPaneTest.ShowDialogLinkLabel rightToLeftShowDialogLabel; // JFormDesigner - End of variables declaration //GEN-END:variables //---- class ShowDialogLinkLabel ------------------------------------------ @@ -315,9 +343,15 @@ public class FlatOptionPaneTest } private void showDialog() { + Component parent = SwingUtilities.windowForComponent( this ); + + // use optionPane as parent if component orientation is different + if( parent.getComponentOrientation().isLeftToRight() != optionPane.getComponentOrientation().isLeftToRight() ) + parent = optionPane; + if( optionPane.getWantsInput() ) { JOptionPane.showInputDialog( - getParent(), + parent, optionPane.getMessage(), titleLabel.getText() + " Title", optionPane.getMessageType(), @@ -326,7 +360,7 @@ public class FlatOptionPaneTest null ); } else { JOptionPane.showOptionDialog( - getParent(), + parent, optionPane.getMessage(), titleLabel.getText() + " Title", optionPane.getOptionType(), diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd index ff83c766..78d9bf17 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8" +JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -12,7 +12,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "flowy,ltr,insets dialog,hidemode 3" "$columnConstraints": "[][][fill]" - "$rowConstraints": "[top][top][top][top][top][top][top][top]" + "$rowConstraints": "[top][top][top][top][top][top][top][top][top]" } ) { name: "panel9" add( new FormComponent( "javax.swing.JLabel" ) { @@ -240,10 +240,40 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 7" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "rightToLeftLabel" + "text": "Right-to-left:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 8" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) { + name: "panel10" + "border": #LineBorder0 + add( new FormComponent( "javax.swing.JOptionPane" ) { + name: "rightToLeftOptionPane" + "messageType": 1 + "message": "المادة 1 يولد جميع الناس أحرارًا متساوين في الكرامة والحقوق. وقد وهبوا عقلاً وضميرًا وعليهم أن يعامل بعضهم بعضًا بروح الإخاء.\nالمادة 1 يولد جميع الناس أحرارًا متساوين في الكرامة والحقوق. وقد وهبوا عقلاً وضميرًا وعليهم أن يعامل بعضهم بعضًا بروح الإخاء.\n\nالمادة 1 يولد جميع الناس أحرارًا متساوين في الكرامة \nوالحقوق. وقد وهبوا عقلاً وضميرًا وعليهم أن يعامل بعضهم بعضًا بروح الإخاء." + "componentOrientation": sfield java.awt.ComponentOrientation RIGHT_TO_LEFT + }, new FormLayoutConstraints( class java.lang.String ) { + "value": "Center" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 8" + } ) + add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) { + name: "rightToLeftShowDialogLabel" + "optionPane": new FormReference( "rightToLeftOptionPane" ) + "titleLabel": new FormReference( "rightToLeftLabel" ) + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 8" + } ) } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 840, 900 ) + "size": new java.awt.Dimension( 895, 1080 ) } ) } } From 1de81d0af56fbcc65b6a3ceff733af9595d03070 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 9 Jul 2021 11:39:35 +0200 Subject: [PATCH 08/16] ComboBox: fixed StackOverflowError when using single renderer instance in multiple comboboxes (regression since commit 4507ce359d5fa2bb1b6fac4e9645f9c27a02d4d2) --- .../formdev/flatlaf/ui/FlatComboBoxUI.java | 8 ++- .../testing/FlatCustomBordersTest.java | 51 +++++++++++++++++++ .../flatlaf/testing/FlatCustomBordersTest.jfd | 38 +++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) 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 5d84415b..876881f7 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 @@ -791,14 +791,20 @@ public class FlatComboBoxUI if( oldBorder == this ) return; // already installed + // component already has a padding border --> uninstall it + // (may happen if single renderer instance is used in multiple comboboxes) + if( oldBorder instanceof CellPaddingBorder ) + ((CellPaddingBorder)oldBorder).uninstall(); + // this border can be installed only at one component + // (may happen if a renderer returns varying components) uninstall(); // remember component where this border was installed for uninstall rendererComponent = jc; // remember old border and replace it - rendererBorder = oldBorder; + rendererBorder = jc.getBorder(); rendererComponent.setBorder( this ); } 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 5f4c5478..fecc5730 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 @@ -47,6 +47,7 @@ public class FlatCustomBordersTest FlatCustomBordersTest() { initComponents(); applyCustomBorders(); + applySpecialComboBoxRenderers(); DefaultComboBoxModel model = new DefaultComboBoxModel<>( new String[] { "text", @@ -123,6 +124,33 @@ public class FlatCustomBordersTest applyCustomComboBoxRendererBorder( comboBox28, null ); } + @SuppressWarnings( "unchecked" ) + private void applySpecialComboBoxRenderers() { + BasicComboBoxRenderer sharedRenderer = new BasicComboBoxRenderer(); + sharedRenderer.setBorder( new LineBorder( ORANGE, UIScale.scale( 2 ) ) ); + comboBox29.setRenderer( sharedRenderer ); + comboBox30.setRenderer( sharedRenderer ); + + comboBox31.setRenderer( new ListCellRenderer() { + JLabel l1 = new JLabel(); + JLabel l2 = new JLabel(); + + @Override + public Component getListCellRendererComponent( JList list, + String value, int index, boolean isSelected, boolean cellHasFocus ) + { + JLabel l = (index % 2 == 0) ? l1 : l2; + l.setText( (value != null) ? value.toString() : "" ); + l.setBorder( new LineBorder( (index % 2 == 0) ? GREEN : RED, UIScale.scale( 2 ) ) ); + l.setBackground( isSelected ? list.getSelectionBackground() : list.getBackground() ); + l.setForeground( isSelected ? list.getSelectionForeground() : list.getForeground() ); + l.setFont( list.getFont() ); + l.setOpaque( true ); + return l; + } + } ); + } + private void applyCustomInsideBorder( JComponent c, String uiKey ) { c.setBorder( new CompoundBorder( UIManager.getBorder( uiKey ), new LineBorder( RED, UIScale.scale( 3 ) ) ) ); } @@ -231,6 +259,11 @@ public class FlatCustomBordersTest textField6 = new JTextField(); textField7 = new JTextField(); textField8 = new JTextField(); + label11 = new JLabel(); + label12 = new JLabel(); + comboBox29 = new JComboBox<>(); + comboBox30 = new JComboBox<>(); + comboBox31 = new JComboBox<>(); //======== this ======== setLayout(new MigLayout( @@ -255,6 +288,8 @@ public class FlatCustomBordersTest "[]" + "[]" + "[]" + + "[]para" + + "[]" + "[]")); //---- label1 ---- @@ -493,6 +528,17 @@ public class FlatCustomBordersTest textField8.putClientProperty("JComponent.roundRect", true); textField8.setText("text"); add(textField8, "cell 4 10"); + + //---- label11 ---- + label11.setText("JComboBox with shared renderer:"); + add(label11, "cell 1 11 2 1"); + + //---- label12 ---- + label12.setText("JComboBox with renderer that uses varying components:"); + add(label12, "cell 3 11 3 1"); + add(comboBox29, "cell 1 12"); + add(comboBox30, "cell 2 12"); + add(comboBox31, "cell 3 12"); // JFormDesigner - End of component initialization //GEN-END:initComponents } @@ -560,6 +606,11 @@ public class FlatCustomBordersTest private JTextField textField6; private JTextField textField7; private JTextField textField8; + private JLabel label11; + private JLabel label12; + private JComboBox comboBox29; + private JComboBox comboBox30; + private JComboBox comboBox31; // JFormDesigner - End of variables declaration //GEN-END:variables //---- class BorderWithIcon ----------------------------------------------- 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 6d67ea4a..f2ca9cd3 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 @@ -6,7 +6,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[][fill][fill][fill][fill][fill][fill][fill]" - "$rowConstraints": "[][][][][][][][][][][]" + "$rowConstraints": "[][][][][][][][][][][]para[][]" } ) { name: "this" add( new FormComponent( "javax.swing.JLabel" ) { @@ -478,6 +478,42 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 10" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label11" + "text": "JComboBox with shared renderer:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 11 2 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label12" + "text": "JComboBox with renderer that uses varying components:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 11 3 1" + } ) + add( new FormComponent( "javax.swing.JComboBox" ) { + name: "comboBox29" + auxiliary() { + "JavaCodeGenerator.typeParameters": "String" + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 12" + } ) + add( new FormComponent( "javax.swing.JComboBox" ) { + name: "comboBox30" + auxiliary() { + "JavaCodeGenerator.typeParameters": "String" + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 12" + } ) + add( new FormComponent( "javax.swing.JComboBox" ) { + name: "comboBox31" + auxiliary() { + "JavaCodeGenerator.typeParameters": "String" + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 12" + } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) "size": new java.awt.Dimension( 915, 715 ) From 74a748d92ed1ececd52843d78fae90768ad5c8ad Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 9 Jul 2021 13:22:37 +0200 Subject: [PATCH 09/16] use LoggingFacade instead of printStackTrace() in flatlaf-extras and flatlaf-demo --- .../src/main/java/com/formdev/flatlaf/demo/ControlBar.java | 3 ++- .../src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java | 3 ++- .../flatlaf/demo/intellijthemes/IJThemesClassGenerator.java | 3 ++- .../flatlaf/demo/intellijthemes/IJThemesManager.java | 3 ++- .../formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java | 5 +++-- .../flatlaf/demo/intellijthemes/IJThemesUpdater.java | 3 ++- .../main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java | 3 ++- .../com/formdev/flatlaf/extras/FlatUIDefaultsInspector.java | 6 ++++-- .../flatlaf/extras/components/FlatComponentExtension.java | 3 ++- 9 files changed, 21 insertions(+), 11 deletions(-) diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/ControlBar.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/ControlBar.java index 534c5570..0c2addd7 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/ControlBar.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/ControlBar.java @@ -28,6 +28,7 @@ import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.nimbus.NimbusLookAndFeel; import com.formdev.flatlaf.*; import com.formdev.flatlaf.extras.FlatAnimatedLafChange; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.UIScale; import net.miginfocom.layout.ConstraintParser; @@ -240,7 +241,7 @@ class ControlBar frame.setSize( Math.max( prefSize.width, width ), Math.max( prefSize.height, height ) ); } catch( Exception ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); } } ); } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java index 893cb429..52626d16 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java @@ -25,6 +25,7 @@ import com.formdev.flatlaf.FlatLightLaf; import com.formdev.flatlaf.FlatPropertiesLaf; import com.formdev.flatlaf.IntelliJTheme; import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.StringUtils; /** @@ -83,7 +84,7 @@ public class DemoPrefs UIManager.setLookAndFeel( lafClassName ); } } catch( Throwable ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); // fallback FlatLightLaf.setup(); diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesClassGenerator.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesClassGenerator.java index e3cdc006..f523e4e6 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesClassGenerator.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesClassGenerator.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import com.formdev.flatlaf.util.LoggingFacade; /** * This tool creates look and feel classes for all themes listed in themes.json. @@ -120,7 +121,7 @@ public class IJThemesClassGenerator Files.write( out, content.getBytes( StandardCharsets.ISO_8859_1 ), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING ); } catch( IOException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); } } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java index 07142025..ece63854 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesManager.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import com.formdev.flatlaf.json.Json; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.StringUtils; /** @@ -46,7 +47,7 @@ class IJThemesManager try( Reader reader = new InputStreamReader( getClass().getResourceAsStream( "themes.json" ), StandardCharsets.UTF_8 ) ) { json = (Map) Json.parse( reader ); } catch( IOException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); return; } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java index 9ea545ee..ee89f571 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java @@ -52,6 +52,7 @@ import com.formdev.flatlaf.IntelliJTheme; import com.formdev.flatlaf.demo.DemoPrefs; import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.StringUtils; import net.miginfocom.swing.*; @@ -259,7 +260,7 @@ public class IJThemesPanel try { UIManager.setLookAndFeel( themeInfo.lafClassName ); } catch( Exception ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); showInformationDialog( "Failed to create '" + themeInfo.lafClassName + "'.", ex ); } } else if( themeInfo.themeFile != null ) { @@ -273,7 +274,7 @@ public class IJThemesPanel DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.FILE_PREFIX + themeInfo.themeFile ); } catch( Exception ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex ); } } else { diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesUpdater.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesUpdater.java index bad7a17a..ac6f2cc1 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesUpdater.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesUpdater.java @@ -23,6 +23,7 @@ import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import com.formdev.flatlaf.util.LoggingFacade; /** * This tool updates all IntelliJ themes listed in themes.json by downloading @@ -61,7 +62,7 @@ public class IJThemesUpdater URLConnection con = url.openConnection(); Files.copy( con.getInputStream(), out, StandardCopyOption.REPLACE_EXISTING ); } catch( IOException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( null, ex ); } } } diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java index 04297140..84ac540f 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatSVGIcon.java @@ -42,6 +42,7 @@ import com.formdev.flatlaf.FlatLaf.DisabledIconProvider; import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.GrayFilter; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.MultiResolutionImageSupport; import com.formdev.flatlaf.util.UIScale; import com.kitfox.svg.SVGDiagram; @@ -335,7 +336,7 @@ public class FlatSVGIcon try { diagram = svgUniverse.getDiagram( url.toURI() ); } catch( URISyntaxException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load SVG icon '" + url + "'.", ex ); } } diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatUIDefaultsInspector.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatUIDefaultsInspector.java index 8457216d..6a49e7c8 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatUIDefaultsInspector.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatUIDefaultsInspector.java @@ -52,6 +52,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.DerivedColor; import com.formdev.flatlaf.util.GrayFilter; import com.formdev.flatlaf.util.HSLColor; +import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.formdev.flatlaf.util.UIScale; @@ -377,11 +378,12 @@ public class FlatUIDefaultsInspector } private Properties loadDerivedColorKeys() { + String name = "/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties"; Properties properties = new Properties(); - try( InputStream in = getClass().getResourceAsStream( "/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties" ) ) { + try( InputStream in = getClass().getResourceAsStream( name ) ) { properties.load( in ); } catch( IOException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load '" + name + "'.", ex ); } return properties; } diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatComponentExtension.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatComponentExtension.java index 29f753c3..b9caa3a4 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatComponentExtension.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatComponentExtension.java @@ -20,6 +20,7 @@ import java.awt.Color; import java.awt.Insets; import javax.swing.JComponent; import javax.swing.UIManager; +import com.formdev.flatlaf.util.LoggingFacade; /** * Base interface for all FlatLaf component extensions. @@ -87,7 +88,7 @@ public interface FlatComponentExtension try { return Enum.valueOf( enumType, (String) value ); } catch( IllegalArgumentException ex ) { - ex.printStackTrace(); + LoggingFacade.INSTANCE.logSevere( "FlatLaf: Unknown enum value '" + value + "' in enum '" + enumType.getName() + "'.", ex ); } } return defaultValue; From cc6d3c1b1a370243ea63939d4462869ec4185b48 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 9 Jul 2021 15:03:16 +0200 Subject: [PATCH 10/16] PasswordField: Caps lock icon no longer painted over long text (issue #172) --- CHANGELOG.md | 1 + .../com/formdev/flatlaf/ui/FlatCaret.java | 20 +++++++++++ .../flatlaf/ui/FlatPasswordFieldUI.java | 35 +++++++++++++++---- .../formdev/flatlaf/ui/FlatTextFieldUI.java | 9 +++++ .../com/formdev/flatlaf/ui/FlatUIUtils.java | 5 +++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25f254a6..9e1d84ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ FlatLaf Change Log non-opaque. (issue #349) - OptionPane: Align wrapped lines to the right if component orientation is right-to-left. (issue #350) +- PasswordField: Caps lock icon no longer painted over long text. (issue #172) - Window decorations: Window title bar width is no longer considered when calculating preferred/minimum width of window. (issue #351) 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 fe28e1c0..83a5aac3 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 @@ -24,6 +24,7 @@ import java.awt.event.FocusEvent; import java.awt.event.MouseEvent; import javax.swing.JFormattedTextField; import javax.swing.plaf.UIResource; +import javax.swing.text.BadLocationException; import javax.swing.text.DefaultCaret; import javax.swing.text.Document; import javax.swing.text.JTextComponent; @@ -142,4 +143,23 @@ public class FlatCaret moveDot( doc.getLength() ); } } + + /** + * @since 1.4 + */ + public void scrollCaretToVisible() { + JTextComponent c = getComponent(); + if( c == null || c.getUI() == null ) + return; + + try { + Rectangle loc = c.getUI().modelToView( c, getDot(), getDotBias() ); + if( loc != null ) { + adjustVisibility( loc ); + damage( loc ); + } + } catch( BadLocationException ex ) { + // ignore + } + } } 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 f15f9701..661fe8c9 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 @@ -17,6 +17,7 @@ package com.formdev.flatlaf.ui; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Shape; import java.awt.Toolkit; import java.awt.event.KeyAdapter; @@ -123,8 +124,10 @@ public class FlatPasswordFieldUI repaint( e ); } private void repaint( KeyEvent e ) { - if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK ) + if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK ) { e.getComponent().repaint(); + scrollCaretToVisible(); + } } }; @@ -169,16 +172,36 @@ public class FlatPasswordFieldUI } protected void paintCapsLock( Graphics g ) { - if( !showCapsLock ) + if( !isCapsLockVisible() ) return; JTextComponent c = getComponent(); - if( !FlatUIUtils.isPermanentFocusOwner( c ) || - !Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK ) ) - return; - int y = (c.getHeight() - capsLockIcon.getIconHeight()) / 2; int x = c.getWidth() - capsLockIcon.getIconWidth() - y; capsLockIcon.paintIcon( c, g, x, y ); } + + /** + * @since 1.4 + */ + protected boolean isCapsLockVisible() { + if( !showCapsLock ) + return false; + + JTextComponent c = getComponent(); + return FlatUIUtils.isPermanentFocusOwner( c ) && + Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK ); + } + + /** + * @since 1.4 + */ + @Override + protected Insets getPadding() { + Insets padding = super.getPadding(); + if( !isCapsLockVisible() ) + return padding; + + return FlatUIUtils.addInsets( padding, new Insets( 0, 0, 0, capsLockIcon.getIconWidth() ) ); + } } 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 8e9db66b..ddc6208a 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 @@ -290,4 +290,13 @@ public class FlatTextFieldUI Object padding = getComponent().getClientProperty( FlatClientProperties.TEXT_FIELD_PADDING ); return (padding instanceof Insets) ? UIScale.scale( (Insets) padding ) : null; } + + /** + * @since 1.4 + */ + protected void scrollCaretToVisible() { + Caret caret = getComponent().getCaret(); + if( caret instanceof FlatCaret ) + ((FlatCaret)caret).scrollCaretToVisible(); + } } 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 dfc27e44..7b288dc3 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 @@ -94,6 +94,11 @@ public class FlatUIUtils } public static Insets addInsets( Insets insets1, Insets insets2 ) { + if( insets1 == null ) + return insets2; + if( insets2 == null ) + return insets1; + return new Insets( insets1.top + insets2.top, insets1.left + insets2.left, From 0b342acec974b27512838040f43336b3965c567a Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 9 Jul 2021 15:14:29 +0200 Subject: [PATCH 11/16] PasswordField: paint caps lock icon on left side in right-to-left component orientation --- CHANGELOG.md | 2 ++ .../java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e1d84ab..b1f98c5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ FlatLaf Change Log - OptionPane: Align wrapped lines to the right if component orientation is right-to-left. (issue #350) - PasswordField: Caps lock icon no longer painted over long text. (issue #172) +- PasswordField: Paint caps lock icon on left side in right-to-left component + orientation. - Window decorations: Window title bar width is no longer considered when calculating preferred/minimum width of window. (issue #351) 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 661fe8c9..e1f74421 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 @@ -177,7 +177,9 @@ public class FlatPasswordFieldUI JTextComponent c = getComponent(); int y = (c.getHeight() - capsLockIcon.getIconHeight()) / 2; - int x = c.getWidth() - capsLockIcon.getIconWidth() - y; + int x = c.getComponentOrientation().isLeftToRight() + ? c.getWidth() - capsLockIcon.getIconWidth() - y + : y; capsLockIcon.paintIcon( c, g, x, y ); } @@ -202,6 +204,8 @@ public class FlatPasswordFieldUI if( !isCapsLockVisible() ) return padding; - return FlatUIUtils.addInsets( padding, new Insets( 0, 0, 0, capsLockIcon.getIconWidth() ) ); + boolean ltr = getComponent().getComponentOrientation().isLeftToRight(); + int iconWidth = capsLockIcon.getIconWidth(); + return FlatUIUtils.addInsets( padding, new Insets( 0, ltr ? 0 : iconWidth, 0, ltr ? iconWidth : 0 ) ); } } From 548d651d29ddfe0a7ed51bf0d303dd449dab20a7 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 10 Jul 2021 11:03:13 +0200 Subject: [PATCH 12/16] PasswordField: move the lower bar of the caps lock icon up a half pixel --- .../main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java index 2ceab38f..64fedf47 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java @@ -44,7 +44,7 @@ public class FlatCapsLockIcon - + @@ -52,7 +52,7 @@ public class FlatCapsLockIcon Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD ); path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false ); - path.append( new Rectangle2D.Float( 5, 12, 6, 2 ), false ); + path.append( new Rectangle2D.Float( 5, 11.5f, 6, 2 ), false ); path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false ); g.fill( path ); } From 4d8b544aede53dfd49c7921366bc0c43280943df Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 10 Jul 2021 13:28:02 +0200 Subject: [PATCH 13/16] UIDefaultsKeysDump: also use FlatTestLaf, which adds missing keys to FlatLafUIKeys.txt --- .../uidefaults/UIDefaultsKeysDump.java | 2 ++ .../flatlaf/themeeditor/FlatLafUIKeys.txt | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsKeysDump.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsKeysDump.java index 93cc7147..b7ecfe72 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsKeysDump.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsKeysDump.java @@ -29,6 +29,7 @@ import java.util.Locale; import javax.swing.UIDefaults; import javax.swing.UIManager; import com.formdev.flatlaf.*; +import com.formdev.flatlaf.testing.FlatTestLaf; /** * Collects all FlatLaf UI defaults keys and dumps them to a file. @@ -60,6 +61,7 @@ public class UIDefaultsKeysDump collectKeys( FlatDarkLaf.class.getName(), keys ); collectKeys( FlatIntelliJLaf.class.getName(), keys ); collectKeys( FlatDarculaLaf.class.getName(), keys ); + collectKeys( FlatTestLaf.class.getName(), keys ); // write key file try( Writer fileWriter = new BufferedWriter( new FileWriter( keysFile ) ) ) { diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 72ccd0c1..d5960513 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -18,6 +18,8 @@ Button.default.background Button.default.boldText Button.default.borderColor Button.default.borderWidth +Button.default.endBackground +Button.default.endBorderColor Button.default.focusColor Button.default.focusedBackground Button.default.focusedBorderColor @@ -25,12 +27,16 @@ Button.default.foreground Button.default.hoverBackground Button.default.hoverBorderColor Button.default.pressedBackground +Button.default.startBackground +Button.default.startBorderColor Button.defaultButtonFollowsFocus Button.disabledBackground Button.disabledBorderColor Button.disabledForeground Button.disabledSelectedBackground Button.disabledText +Button.endBackground +Button.endBorderColor Button.focusInputMap Button.focusedBackground Button.focusedBorderColor @@ -49,6 +55,8 @@ Button.rollover Button.selectedBackground Button.selectedForeground Button.shadow +Button.startBackground +Button.startBorderColor Button.textIconGap Button.textShiftOffset Button.toolbar.hoverBackground @@ -142,6 +150,7 @@ ComboBox.buttonBackground ComboBox.buttonDarkShadow ComboBox.buttonDisabledArrowColor ComboBox.buttonEditableBackground +ComboBox.buttonFocusedBackground ComboBox.buttonHighlight ComboBox.buttonHoverArrowColor ComboBox.buttonPressedArrowColor @@ -150,6 +159,7 @@ ComboBox.buttonStyle ComboBox.disabledBackground ComboBox.disabledForeground ComboBox.editorColumns +ComboBox.focusedBackground ComboBox.font ComboBox.foreground ComboBox.isEnterSelectablePopup @@ -157,6 +167,7 @@ ComboBox.maximumRowCount ComboBox.minimumWidth ComboBox.noActionOnKeyNavigation ComboBox.padding +ComboBox.popupBackground ComboBox.selectionBackground ComboBox.selectionForeground ComboBox.timeFactor @@ -197,6 +208,7 @@ EditorPane.caretBlinkRate EditorPane.caretForeground EditorPane.disabledBackground EditorPane.focusInputMap +EditorPane.focusedBackground EditorPane.font EditorPane.foreground EditorPane.inactiveBackground @@ -226,6 +238,7 @@ FormattedTextField.caretBlinkRate FormattedTextField.caretForeground FormattedTextField.disabledBackground FormattedTextField.focusInputMap +FormattedTextField.focusedBackground FormattedTextField.font FormattedTextField.foreground FormattedTextField.inactiveBackground @@ -295,7 +308,9 @@ JXBusyLabel.baseColor JXBusyLabel.highlightColor JXDatePicker.border JXHeader.background +JXHeader.descriptionForeground JXHeader.startBackground +JXHeader.titleForeground JXMonthView.arrowColor JXMonthView.background JXMonthView.daysOfTheWeekForeground @@ -475,6 +490,11 @@ OptionPane.buttonPadding OptionPane.errorIcon OptionPane.font OptionPane.foreground +OptionPane.icon.errorColor +OptionPane.icon.foreground +OptionPane.icon.informationColor +OptionPane.icon.questionColor +OptionPane.icon.warningColor OptionPane.iconMessageGap OptionPane.informationIcon OptionPane.maxCharactersPerLine @@ -500,6 +520,7 @@ PasswordField.caretForeground PasswordField.disabledBackground PasswordField.echoChar PasswordField.focusInputMap +PasswordField.focusedBackground PasswordField.font PasswordField.foreground PasswordField.inactiveBackground @@ -651,11 +672,14 @@ Slider.foreground Slider.highlight Slider.horizontalSize Slider.hoverThumbColor +Slider.hoverTrackColor Slider.minimumHorizontalSize Slider.minimumVerticalSize Slider.onlyLeftMouseButtonDrag Slider.pressedThumbColor +Slider.pressedTrackColor Slider.shadow +Slider.thumbBorderColor Slider.thumbColor Slider.thumbSize Slider.tickColor @@ -678,6 +702,7 @@ Spinner.disabledBackground Spinner.disabledForeground Spinner.editorAlignment Spinner.editorBorderPainted +Spinner.focusedBackground Spinner.font Spinner.foreground Spinner.padding @@ -753,6 +778,7 @@ TabbedPane.tabHeight TabbedPane.tabInsets TabbedPane.tabRunOverlay TabbedPane.tabSelectionHeight +TabbedPane.tabSeparatorColor TabbedPane.tabSeparatorsFullHeight TabbedPane.tabWidthMode TabbedPane.tabsOpaque @@ -820,6 +846,7 @@ TextArea.caretBlinkRate TextArea.caretForeground TextArea.disabledBackground TextArea.focusInputMap +TextArea.focusedBackground TextArea.font TextArea.foreground TextArea.inactiveBackground @@ -838,6 +865,7 @@ TextField.caretForeground TextField.darkShadow TextField.disabledBackground TextField.focusInputMap +TextField.focusedBackground TextField.font TextField.foreground TextField.highlight @@ -856,6 +884,7 @@ TextPane.caretBlinkRate TextPane.caretForeground TextPane.disabledBackground TextPane.focusInputMap +TextPane.focusedBackground TextPane.font TextPane.foreground TextPane.inactiveBackground @@ -865,6 +894,7 @@ TextPane.selectionBackground TextPane.selectionForeground TextPaneUI TitlePane.background +TitlePane.borderColor TitlePane.buttonHoverBackground TitlePane.buttonMaximizedHeight TitlePane.buttonPressedBackground @@ -902,9 +932,11 @@ ToggleButton.disabledBackground ToggleButton.disabledSelectedBackground ToggleButton.disabledText ToggleButton.focusInputMap +ToggleButton.focusedBackground ToggleButton.font ToggleButton.foreground ToggleButton.highlight +ToggleButton.hoverBackground ToggleButton.iconTextGap ToggleButton.light ToggleButton.margin @@ -916,6 +948,7 @@ ToggleButton.shadow ToggleButton.tab.disabledUnderlineColor ToggleButton.tab.focusBackground ToggleButton.tab.hoverBackground +ToggleButton.tab.selectedBackground ToggleButton.tab.underlineColor ToggleButton.tab.underlineHeight ToggleButton.textIconGap @@ -962,6 +995,7 @@ Tree.dropCellBackground Tree.dropCellForeground Tree.dropLineColor Tree.editorBorder +Tree.editorBorderSelectionColor Tree.expandedIcon Tree.focusInputMap Tree.focusInputMap.RightToLeft From 8b585deb78c1e8563224501aca5aa27699e3e9f1 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 10 Jul 2021 13:32:30 +0200 Subject: [PATCH 14/16] ToolBar: support focusable buttons in toolbar (issue #346) fixed focusable state when switching to/from other Laf --- CHANGELOG.md | 2 + .../com/formdev/flatlaf/ui/FlatToolBarUI.java | 59 +++++++++++++++++-- .../com/formdev/flatlaf/FlatLaf.properties | 1 + .../uidefaults/FlatDarkLaf_1.8.0_202.txt | 1 + .../uidefaults/FlatLightLaf_1.8.0_202.txt | 1 + .../uidefaults/FlatTestLaf_1.8.0_202.txt | 1 + .../flatlaf/testing/FlatTestLaf.properties | 5 ++ .../flatlaf/themeeditor/FlatLafUIKeys.txt | 1 + 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1f98c5f..dd68d6d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ FlatLaf Change Log - Table and PopupFactory: Use `StackWalker` in Java 9+ for better performance. (issue #334) - ToolBar: Paint focus indicator for focused button in toolbar. (issue #346) +- ToolBar: Support focusable buttons in toolbar (set UI values + `ToolBar.focusableButtons` to `true`). (issue #346) #### Fixed bugs diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java index 49b00e49..86af0906 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java @@ -22,6 +22,7 @@ import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolBarUI; @@ -41,15 +42,47 @@ import javax.swing.plaf.basic.BasicToolBarUI; * @uiDefault ToolBar.floatingForeground Color * @uiDefault ToolBar.isRollover boolean * + * + * + * @uiDefault ToolBar.focusableButtons boolean + * * @author Karl Tauber */ public class FlatToolBarUI extends BasicToolBarUI { + /** @since 1.4 */ + protected boolean focusableButtons; + public static ComponentUI createUI( JComponent c ) { return new FlatToolBarUI(); } + @Override + public void installUI( JComponent c ) { + super.installUI( c ); + + // disable focusable state of buttons (when switching from another Laf) + if( !focusableButtons ) + setButtonsFocusable( false ); + } + + @Override + public void uninstallUI( JComponent c ) { + super.uninstallUI( c ); + + // re-enable focusable state of buttons (when switching to another Laf) + if( !focusableButtons ) + setButtonsFocusable( true ); + } + + @Override + protected void installDefaults() { + super.installDefaults(); + + focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" ); + } + @Override protected ContainerListener createToolBarContListener() { return new ToolBarContListener() { @@ -57,22 +90,36 @@ public class FlatToolBarUI public void componentAdded( ContainerEvent e ) { super.componentAdded( e ); - Component c = e.getChild(); - if( c instanceof AbstractButton ) - c.setFocusable( false ); + if( !focusableButtons ) { + Component c = e.getChild(); + if( c instanceof AbstractButton ) + c.setFocusable( false ); + } } @Override public void componentRemoved( ContainerEvent e ) { super.componentRemoved( e ); - Component c = e.getChild(); - if( c instanceof AbstractButton ) - c.setFocusable( true ); + if( !focusableButtons ) { + Component c = e.getChild(); + if( c instanceof AbstractButton ) + c.setFocusable( true ); + } } }; } + /** + * @since 1.4 + */ + protected void setButtonsFocusable( boolean focusable ) { + for( Component c : toolBar.getComponents() ) { + if( c instanceof AbstractButton ) + c.setFocusable( focusable ); + } + } + // disable rollover border @Override protected void setBorderToRollover( Component c ) {} @Override protected void setBorderToNonRollover( Component c ) {} diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 52e8bff9..90c86413 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -752,6 +752,7 @@ ToolBar.separatorWidth = 7 ToolBar.separatorColor = $Separator.foreground ToolBar.spacingBorder = $Button.toolbar.spacingInsets +ToolBar.focusableButtons = false #---- ToolTipManager ---- diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt index 69102d69..8ddfceaa 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt @@ -1249,6 +1249,7 @@ ToolBar.dockingBackground #3c3f41 javax.swing.plaf.ColorUIResource [UI] ToolBar.dockingForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingBackground #3c3f41 javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingForeground #888888 javax.swing.plaf.ColorUIResource [UI] +ToolBar.focusableButtons false ToolBar.font [active] $defaultFont [UI] ToolBar.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI] ToolBar.gripColor #adadad javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt index 272cc8a7..2a118223 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt @@ -1254,6 +1254,7 @@ ToolBar.dockingBackground #f2f2f2 javax.swing.plaf.ColorUIResource [UI] ToolBar.dockingForeground #000000 javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingBackground #f2f2f2 javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingForeground #8c8c8c javax.swing.plaf.ColorUIResource [UI] +ToolBar.focusableButtons false ToolBar.font [active] $defaultFont [UI] ToolBar.foreground #000000 javax.swing.plaf.ColorUIResource [UI] ToolBar.gripColor #afafaf javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt index 62a7b049..833e85f4 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt @@ -1263,6 +1263,7 @@ ToolBar.dockingBackground #ccffcc javax.swing.plaf.ColorUIResource [UI] ToolBar.dockingForeground #ff0000 javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingBackground #ccffcc javax.swing.plaf.ColorUIResource [UI] ToolBar.floatingForeground #000088 javax.swing.plaf.ColorUIResource [UI] +ToolBar.focusableButtons true ToolBar.font [active] $defaultFont [UI] ToolBar.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] ToolBar.gripColor #afafaf javax.swing.plaf.ColorUIResource [UI] 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 589e78dd..3d686a41 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 @@ -400,6 +400,11 @@ ToggleButton.pressedBackground = #FFC800 ToggleButton.toolbar.selectedBackground = #ddd +#---- ToolBar ---- + +ToolBar.focusableButtons = true + + #---- ToolTip ---- ToolTip.background = #eef diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index d5960513..6c84a82b 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -966,6 +966,7 @@ ToolBar.dockingBackground ToolBar.dockingForeground ToolBar.floatingBackground ToolBar.floatingForeground +ToolBar.focusableButtons ToolBar.font ToolBar.foreground ToolBar.gripColor From 94375b7d36dc6ae02309f5dcc04d2cae38b3601b Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 10 Jul 2021 20:59:34 +0200 Subject: [PATCH 15/16] Extras: added support for client property `JTextField.padding` (for commit a9dcf09d1312743519c9874fb450f8ac2542856d) --- .../components/FlatFormattedTextField.java | 22 +++++++++++++++++++ .../extras/components/FlatPasswordField.java | 22 +++++++++++++++++++ .../extras/components/FlatTextField.java | 22 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java index 5f943bfe..4ebc554d 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Insets; import javax.swing.JFormattedTextField; import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy; @@ -61,6 +62,27 @@ public class FlatFormattedTextField } + /** + * Returns the padding of the text. + * + * @since 1.4 + */ + public Insets getPadding() { + return (Insets) getClientProperty( TEXT_FIELD_PADDING ); + } + + /** + * 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. + * + * @since 1.4 + */ + public void setPadding( Insets padding ) { + putClientProperty( TEXT_FIELD_PADDING, padding ); + } + + /** * Returns minimum width of a component. */ diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java index 93b88299..86495da2 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Insets; import javax.swing.JPasswordField; import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy; @@ -61,6 +62,27 @@ public class FlatPasswordField } + /** + * Returns the padding of the text. + * + * @since 1.4 + */ + public Insets getPadding() { + return (Insets) getClientProperty( TEXT_FIELD_PADDING ); + } + + /** + * 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. + * + * @since 1.4 + */ + public void setPadding( Insets padding ) { + putClientProperty( TEXT_FIELD_PADDING, padding ); + } + + /** * Returns minimum width of a component. */ diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java index a43d195b..bfa22dd2 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Insets; import javax.swing.JTextField; /** @@ -63,6 +64,27 @@ public class FlatTextField } + /** + * Returns the padding of the text. + * + * @since 1.4 + */ + public Insets getPadding() { + return (Insets) getClientProperty( TEXT_FIELD_PADDING ); + } + + /** + * 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. + * + * @since 1.4 + */ + public void setPadding( Insets padding ) { + putClientProperty( TEXT_FIELD_PADDING, padding ); + } + + /** * Returns minimum width of a component. */ From fb44c8fbe4ea607a644670946e56897323e2eac1 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 10 Jul 2021 21:05:26 +0200 Subject: [PATCH 16/16] TextField: fixed location of placeholder text if paddings are used (e.g. in ComboBox) (for commit a9dcf09d1312743519c9874fb450f8ac2542856d) --- .../com/formdev/flatlaf/ui/FlatTextFieldUI.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 ddc6208a..874d4461 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 @@ -157,7 +157,7 @@ public class FlatTextFieldUI @Override protected void paintSafely( Graphics g ) { paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground ); - paintPlaceholder( g, getComponent(), placeholderForeground ); + paintPlaceholder( g ); super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) ); } @@ -213,7 +213,9 @@ public class FlatTextFieldUI return background; } - static void paintPlaceholder( Graphics g, JTextComponent c, Color placeholderForeground ) { + protected void paintPlaceholder( Graphics g ) { + JTextComponent c = getComponent(); + // check whether text component is empty if( c.getDocument().getLength() > 0 ) return; @@ -228,16 +230,14 @@ public class FlatTextFieldUI return; // compute placeholder location - Insets insets = c.getInsets(); + Rectangle r = getVisibleEditorRect(); FontMetrics fm = c.getFontMetrics( c.getFont() ); - int x = insets.left; - int y = insets.top + fm.getAscent() + ((c.getHeight() - insets.top - insets.bottom - fm.getHeight()) / 2); + int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2); // paint placeholder g.setColor( placeholderForeground ); - String clippedPlaceholder = JavaCompatibility.getClippedString( jc, fm, - (String) placeholder, c.getWidth() - insets.left - insets.right ); - FlatUIUtils.drawString( c, g, clippedPlaceholder, x, y ); + String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, (String) placeholder, r.width ); + FlatUIUtils.drawString( c, g, clippedPlaceholder, r.x, y ); } @Override