Compare commits

..

22 Commits
3.5 ... 3.5.2

Author SHA1 Message Date
Karl Tauber
c29a276188 release 3.5.2 2024-10-18 13:28:53 +02:00
Karl Tauber
d1694aa8bd FlatClientProperties and FlatSystemProperties: javadoc fixes 2024-10-18 13:28:07 +02:00
Karl Tauber
570cf6fc51 FlatLaf window decorations: added client property JRootPane.titleBarHeight to allow specifying a (larger) preferred height for the title bar (issue #897) 2024-10-17 19:58:58 +02:00
Karl Tauber
8eab86e489 FlatLaf window decorations: strech iconify/maximize/close buttons to always fill whole title bar height (issue #897) 2024-10-17 19:49:51 +02:00
Karl Tauber
566568f61a Windows: fixed repaint issues (ghosting) on some systems by setting sun.java2d.d3d.onscreen to false (issue #887) 2024-10-17 13:19:04 +02:00
Karl Tauber
56a73a4d17 Popup: added system property flatlaf.useRoundedPopupBorder to allow disabling native rounded popup borders (PRs #643 and #772) 2024-10-15 00:29:15 +02:00
Karl Tauber
656d25b75e Popup: setup rounded popup border after window was created (no longer create window ourself using addNotify()) to (hopefully) fix repaint issues on some Windows 11 systems after first showing a popup (issue #887, PR #643) 2024-10-12 23:25:59 +02:00
Karl Tauber
dcdc80ade3 Testing: FlatOptionPaneTest: test option pane with custom title bar icon (issue #886) 2024-10-12 00:28:19 +02:00
Karl Tauber
09f2d65d5e change snapshot version from 3.6-SNAPSHOT to 3.5.2-SNAPSHOT 2024-10-11 19:27:23 +02:00
Karl Tauber
b304d46f7e TextComponents: fixed too fast scrolling in multi-line text components when using touchpads (e.g. on macOS) (issue #892) 2024-10-11 19:18:00 +02:00
Karl Tauber
3391f971ec GitHub Actions: build using Java 23 2024-10-11 15:16:49 +02:00
Karl Tauber
778fed27a5 update to Gradle 8.10.2 2024-10-11 15:14:11 +02:00
Karl Tauber
1755dbc877 README.md updated 2024-10-11 15:11:56 +02:00
Karl Tauber
4e6f538519 ToolBar: fixed endless loop if button in Toolbar has focus and is made invisible (issue #884) 2024-09-29 19:26:37 +02:00
Karl Tauber
a6ecb0ef85 FlatLaf window decorations on Windows: fixed possible application freeze when using custom component that overrides Component.contains(int x, int y) and invokes SwingUtilities.convertPoint() (or similar) from the overridden method (issue #878) 2024-09-04 00:48:42 +02:00
Karl Tauber
438ec6ac5c release 3.5.1 2024-08-05 18:17:34 +02:00
Karl Tauber
8089e66642 SubMenuUsabilityHelper: added system property flatlaf.useSubMenuSafeTriangle to allow disabling submenu safe triangle for SWTSwing (issue #870)
also check whether EventQueue.push() succeeded; if not, disable submenu safe triangle
2024-08-05 13:56:43 +02:00
Karl Tauber
d27e0561f2 HiDPI: fixed occasional wrong repaint areas when using HiDPIUtils.installHiDPIRepaintManager() (see PR #864) 2024-08-04 15:14:46 +02:00
Karl Tauber
97b21bfa8b HTML: fixed occasional cutoff wrapped text when using multi-line text in HTML tags <h1>...<h6>, <code>, <kbd>, <big>, <small> or <samp> (issue #873; regression in 3.5) 2024-08-04 14:45:17 +02:00
Karl Tauber
ec4343ed30 TabbedPane: fixed ArrayIndexOutOfBoundsException in case of using "card" tab type and using a custom tab selection model that returns -1 for selected tab (issue #875) 2024-08-03 00:00:00 +02:00
Karl Tauber
948decb3b5 Popup: fixed UnsupportedOperationException: PERPIXEL_TRANSLUCENT translucency is not supported exception on Haiku OS when showing popup (partly) outside of window (issue #869) 2024-08-02 23:47:29 +02:00
Karl Tauber
d510fee7f6 CHANGELOG.md: moved note regarding disabled rounded popup border on macOS from 3.4.1 to 3.5 (wrong in commit 32b0f1ba10) 2024-07-17 00:23:41 +02:00
29 changed files with 541 additions and 86 deletions

View File

@@ -33,10 +33,11 @@ jobs:
- 11 # LTS - 11 # LTS
- 17 # LTS - 17 # LTS
- 21 # LTS - 21 # LTS
- 23 # latest
toolchain: [""] toolchain: [""]
include: # include:
- java: 21 # - java: 21
toolchain: 22 # latest # toolchain: 22 # latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -1,6 +1,56 @@
FlatLaf Change Log FlatLaf Change Log
================== ==================
## 3.5.2
#### Fixed bugs
- Windows: Fixed repaint issues (ghosting) on some systems (probably depending
on graphics card/driver). This is done by setting Java system property
`sun.java2d.d3d.onscreen` to `false` (but only if `sun.java2d.d3d.onscreen`,
`sun.java2d.d3d` and `sun.java2d.noddraw` are not yet set), which disables
usage of Windows Direct3D (DirectX) onscreen surfaces. Component rendering
still uses Direct3D. (issue #887)
- FlatLaf window decorations:
- Iconify/maximize/close buttons did not fill whole title bar height, if some
custom component in menu bar increases title bar height. (issue #897)
- Windows: Fixed possible application freeze when using custom component that
overrides `Component.contains(int x, int y)` and invokes
`SwingUtilities.convertPoint()` (or similar) from the overridden method.
(issue #878)
- TextComponents: Fixed too fast scrolling in multi-line text components when
using touchpads (e.g. on macOS). (issue #892)
- ToolBar: Fixed endless loop if button in Toolbar has focus and is made
invisible. (issue #884)
#### Other Changes
- FlatLaf window decorations: Added client property `JRootPane.titleBarHeight`
to allow specifying a (larger) preferred height for the title bar. (issue
#897)
- Added system property `flatlaf.useRoundedPopupBorder` to allow disabling
native rounded popup borders on Windows 11 and macOS. On macOS 14.4+, where
rounded popup borders are disabled since FlatLaf 3.5 because of occasional
problems, you can use this to enable rounded popup borders (at your risk).
## 3.5.1
#### Fixed bugs
- HTML: Fixed occasional cutoff wrapped text when using multi-line text in HTML
tags `<h1>`...`<h6>`, `<code>`, `<kbd>`, `<big>`, `<small>` or `<samp>`.
(issue #873; regression in 3.5)
- Popup: Fixed `UnsupportedOperationException: PERPIXEL_TRANSLUCENT translucency
is not supported` exception on Haiku OS when showing popup (partly) outside of
window. (issue #869)
- HiDPI: Fixed occasional wrong repaint areas when using
`HiDPIUtils.installHiDPIRepaintManager()`. (see PR #864)
- Added system property `flatlaf.useSubMenuSafeTriangle` to allow disabling
submenu safe triangle (PR #490) for
[SWTSwing](https://github.com/Chrriis/SWTSwing). (issue #870)
## 3.5 ## 3.5
#### New features and improvements #### New features and improvements
@@ -16,6 +66,13 @@ FlatLaf Change Log
#### Fixed bugs #### Fixed bugs
- macOS: Disabled rounded popup border (see PR #772) on macOS 14.4+ because it
may freeze the application and crash the macOS WindowServer process (reports
vary from Finder restarts to OS restarts). This is a temporary change until a
solution is found. See NetBeans issues
[apache/netbeans#7560](https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215)
and
[apache/netbeans#6647](https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442).
- FlatLaf window decorations: Window top border on Windows 10 in "full window - FlatLaf window decorations: Window top border on Windows 10 in "full window
content" mode was not fully repainted when activating or deactivating window. content" mode was not fully repainted when activating or deactivating window.
(issue #809) (issue #809)
@@ -70,13 +127,6 @@ FlatLaf Change Log
(some security software allows loading native library but blocks method (some security software allows loading native library but blocks method
invocation). invocation).
- macOS: Fixed crash when running in WebSwing. (issue #826; regression in 3.4) - macOS: Fixed crash when running in WebSwing. (issue #826; regression in 3.4)
- macOS: Disabled rounded popup border (see PR #772) on macOS 14.4+ because it
may freeze the application and crash the macOS WindowServer process (reports
vary from Finder restarts to OS restarts). This is a temporary change until a
solution is found. See NetBeans issues
[apache/netbeans#7560](https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215)
and
[apache/netbeans#6647](https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442).
#### Incompatibilities #### Incompatibilities

View File

@@ -33,14 +33,20 @@ FlatLaf can use 3rd party themes created for IntelliJ Platform (see
Sponsors Sponsors
-------- --------
### Current Sponsors
[![None Sponsors](images/none-sponsors.png)](https://www.formdev.com/flatlaf/sponsor/)
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
### Previous Sponsors
<a href="https://www.ej-technologies.com/"><img src="https://www.formdev.com/flatlaf/sponsor/ej-technologies.png" width="200" alt="ej-technologies" title="ej-technologies - Java APM, Java Profiler, Java Installer Builder"></a> <a href="https://www.ej-technologies.com/"><img src="https://www.formdev.com/flatlaf/sponsor/ej-technologies.png" width="200" alt="ej-technologies" title="ej-technologies - Java APM, Java Profiler, Java Installer Builder"></a>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
<a href="https://www.dbvis.com/"><img src="https://www.formdev.com/flatlaf/sponsor/dbvisualizer.svg" width="200" alt="DbVisualizer" title="DbVisualizer - SQL Client and Editor"></a> <a href="https://www.dbvis.com/"><img src="https://www.formdev.com/flatlaf/sponsor/dbvisualizer.svg" width="200" alt="DbVisualizer" title="DbVisualizer - SQL Client and Editor"></a>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
<a href="https://www.dscsag.com/"><img src="https://www.formdev.com/flatlaf/sponsor/DSC.png" height="48" alt="DSC Software AG" title="DSC Software AG - Your Companion for Integrative PLM"></a> <a href="https://www.dscsag.com/"><img src="https://www.formdev.com/flatlaf/sponsor/DSC.png" height="48" alt="DSC Software AG" title="DSC Software AG - Your Companion for Integrative PLM"></a>
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
Demo Demo
---- ----

View File

@@ -1,5 +1,5 @@
#Signature file v4.1 #Signature file v4.1
#Version 3.5 #Version 3.5.2
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType" fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
@@ -100,6 +100,7 @@ fld public final static java.lang.String TEXT_FIELD_TRAILING_COMPONENT = "JTextF
fld public final static java.lang.String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon" fld public final static java.lang.String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon"
fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground" fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground"
fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground" fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"
fld public final static java.lang.String TITLE_BAR_HEIGHT = "JRootPane.titleBarHeight"
fld public final static java.lang.String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose" fld public final static java.lang.String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose"
fld public final static java.lang.String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon" fld public final static java.lang.String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon"
fld public final static java.lang.String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify" fld public final static java.lang.String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify"
@@ -223,6 +224,7 @@ meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleab
meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults() meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults()
meth public static java.util.function.Function<java.lang.String,java.awt.Color> getSystemColorGetter() meth public static java.util.function.Function<java.lang.String,java.awt.Color> getSystemColorGetter()
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float) meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
meth public static void disableWindowsD3Donscreen()
meth public static void hideMnemonics() meth public static void hideMnemonics()
meth public static void initIconColors(javax.swing.UIDefaults,boolean) meth public static void initIconColors(javax.swing.UIDefaults,boolean)
meth public static void installLafInfo(java.lang.String,java.lang.Class<? extends javax.swing.LookAndFeel>) meth public static void installLafInfo(java.lang.String,java.lang.Class<? extends javax.swing.LookAndFeel>)
@@ -296,6 +298,8 @@ fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flat
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations" fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
anno 0 java.lang.Deprecated() anno 0 java.lang.Deprecated()
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary" fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
fld public final static java.lang.String USE_ROUNDED_POPUP_BORDER = "flatlaf.useRoundedPopupBorder"
fld public final static java.lang.String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle"
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection" fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont" fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations" fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"

View File

@@ -461,7 +461,7 @@ public interface FlatClientProperties
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority * {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
* than UI default {@code TitlePane.useWindowDecorations}. * than UI default {@code TitlePane.useWindowDecorations}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -481,7 +481,7 @@ public interface FlatClientProperties
* {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority * {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority
* than UI default {@code TitlePane.menuBarEmbedded}. * than UI default {@code TitlePane.menuBarEmbedded}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -507,6 +507,8 @@ public interface FlatClientProperties
* The user can left-click-and-drag on the title bar area to move the window, * The user can left-click-and-drag on the title bar area to move the window,
* except when clicking on a component that processes mouse events (e.g. buttons or menus). * except when clicking on a component that processes mouse events (e.g. buttons or menus).
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -537,7 +539,7 @@ public interface FlatClientProperties
* <p> * <p>
* This client property has higher priority than UI default {@code TitlePane.showIcon}. * This client property has higher priority than UI default {@code TitlePane.showIcon}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -553,6 +555,8 @@ public interface FlatClientProperties
* Setting this shows/hides the windows title * Setting this shows/hides the windows title
* for the {@code JFrame} or {@code JDialog} that contains the root pane. * for the {@code JFrame} or {@code JDialog} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -567,6 +571,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "iconify" button * Setting this shows/hides the "iconify" button
* for the {@code JFrame} that contains the root pane. * for the {@code JFrame} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -581,6 +587,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "maximize/restore" button * Setting this shows/hides the "maximize/restore" button
* for the {@code JFrame} that contains the root pane. * for the {@code JFrame} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -595,6 +603,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "close" button * Setting this shows/hides the "close" button
* for the {@code JFrame} or {@code JDialog} that contains the root pane. * for the {@code JFrame} or {@code JDialog} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -605,7 +615,7 @@ public interface FlatClientProperties
/** /**
* Background color of window title bar (requires enabled window decorations). * Background color of window title bar (requires enabled window decorations).
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color} * <strong>Value type</strong> {@link java.awt.Color}
@@ -617,7 +627,7 @@ public interface FlatClientProperties
/** /**
* Foreground color of window title bar (requires enabled window decorations). * Foreground color of window title bar (requires enabled window decorations).
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color} * <strong>Value type</strong> {@link java.awt.Color}
@@ -626,10 +636,24 @@ public interface FlatClientProperties
*/ */
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"; String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
/**
* Specifies the preferred height of title bar (requires enabled window decorations).
* <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Integer}
*
* @since 3.5.2
*/
String TITLE_BAR_HEIGHT = "JRootPane.titleBarHeight";
/** /**
* Specifies whether the glass pane should have full height and overlap the title bar, * Specifies whether the glass pane should have full height and overlap the title bar,
* if FlatLaf window decorations are enabled. Default is {@code false}. * if FlatLaf window decorations are enabled. Default is {@code false}.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *

View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Image; import java.awt.Image;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.Toolkit; import java.awt.Toolkit;
@@ -119,6 +120,46 @@ public abstract class FlatLaf
private static String preferredSemiboldFontFamily; private static String preferredSemiboldFontFamily;
private static String preferredMonospacedFontFamily; private static String preferredMonospacedFontFamily;
static {
// see disableWindowsD3Donscreen() for details
// https://github.com/JFormDesigner/FlatLaf/issues/887
if( SystemInfo.isWindows &&
System.getProperty( "sun.java2d.d3d.onscreen" ) == null &&
System.getProperty( "sun.java2d.d3d" ) == null &&
System.getProperty( "sun.java2d.noddraw" ) == null )
System.setProperty( "sun.java2d.d3d.onscreen", "false" );
}
/**
* Disable usage of Windows Direct3D (DirectX) onscreen surfaces because this may lead to
* repaint issues (ghosting) on some systems (probably depending on graphics card/driver).
* Problem occurs usually when a small heavy-weight popup window (menu, combobox, tooltip) is shown.
* <p>
* Sets system property {@code sun.java2d.d3d.onscreen} to {@code false},
* but only if {@code sun.java2d.d3d.onscreen}, {@code sun.java2d.d3d}
* and {@code sun.java2d.noddraw} are not yet set.
* <p>
* <strong>Note</strong>: Must be invoked very early before the graphics environment is created.
* <p>
* This method is automatically invoked when loading this class,
* which is usually before the graphics environment is created.
* E.g. when doing {@code FlatLightLaf.setup()} or
* {@code UIManager.setLookAndFeel( "com.formdev.flatlaf.FlatLightLaf" )}.
* <p>
* However, it may be invoked too late if you use some methods from {@link UIManager}
* of {@link GraphicsEnvironment} before setting look and feel.
* E.g. {@link UIManager#put(Object, Object)}.
* In that case invoke this method yourself very early.
* <p>
* <strong>Tip</strong>: How to find out when the graphics environment is created?
* Set a breakpoint at constructor of class {@link GraphicsEnvironment} and look at the stack.
*
* @since 3.5.2
*/
public static void disableWindowsD3Donscreen() {
// dummy method used to trigger invocation of "static {...}" block
}
/** /**
* Sets the application look and feel to the given LaF * Sets the application look and feel to the given LaF
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}. * using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.

View File

@@ -82,7 +82,7 @@ public interface FlatSystemProperties
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and * {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
* UI default {@code TitlePane.useWindowDecorations}. * UI default {@code TitlePane.useWindowDecorations}.
* <p> * <p>
* (requires Window 10/11) * (requires Windows 10/11)
* <p> * <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br> * <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> none * <strong>Default</strong> none
@@ -99,7 +99,7 @@ public interface FlatSystemProperties
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations. * Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
* Then FlatLaf native window decorations are used. * Then FlatLaf native window decorations are used.
* <p> * <p>
* (requires Window 10/11) * (requires Windows 10/11)
* <p> * <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br> * <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1) * <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
@@ -120,7 +120,7 @@ public interface FlatSystemProperties
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and * {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
* UI default {@code TitlePane.menuBarEmbedded}. * UI default {@code TitlePane.menuBarEmbedded}.
* <p> * <p>
* (requires Window 10/11) * (requires Windows 10/11)
* <p> * <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br> * <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> none * <strong>Default</strong> none
@@ -135,6 +135,18 @@ public interface FlatSystemProperties
*/ */
String ANIMATION = "flatlaf.animation"; String ANIMATION = "flatlaf.animation";
/**
* Specifies whether native rounded popup borders should be used (if supported by operating system).
* <p>
* (requires Window 11 or macOS)
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> {@code true}; except on macOS 14.4+ where it is {@code false}
*
* @since 3.5.2
*/
String USE_ROUNDED_POPUP_BORDER = "flatlaf.useRoundedPopupBorder";
/** /**
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens. * Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
* <p> * <p>
@@ -204,6 +216,16 @@ public interface FlatSystemProperties
*/ */
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath"; String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
/**
* Specifies whether safe triangle is used to improve usability of submenus.
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> {@code true}
*
* @since 3.5.1
*/
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
/** /**
* Checks whether a system property is set and returns {@code true} if its value * Checks whether a system property is set and returns {@code true} if its value
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}. * is {@code "true"} (case-insensitive), otherwise it returns {@code false}.

View File

@@ -45,6 +45,7 @@ import javax.swing.UIManager;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.LoggingFacade;
/** /**
* Improves usability of submenus by using a * Improves usability of submenus by using a
@@ -64,6 +65,7 @@ class SubMenuUsabilityHelper
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607 // https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
private static SubMenuUsabilityHelper instance; private static SubMenuUsabilityHelper instance;
private boolean eventQueuePushNotSupported;
private SubMenuEventQueue subMenuEventQueue; private SubMenuEventQueue subMenuEventQueue;
private SafeTrianglePainter safeTrianglePainter; private SafeTrianglePainter safeTrianglePainter;
private boolean changePending; private boolean changePending;
@@ -83,6 +85,9 @@ class SubMenuUsabilityHelper
if( instance != null ) if( instance != null )
return false; return false;
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_SUB_MENU_SAFE_TRIANGLE, true ) )
return false;
instance = new SubMenuUsabilityHelper(); instance = new SubMenuUsabilityHelper();
MenuSelectionManager.defaultManager().addChangeListener( instance ); MenuSelectionManager.defaultManager().addChangeListener( instance );
return true; return true;
@@ -99,7 +104,7 @@ class SubMenuUsabilityHelper
@Override @Override
public void stateChanged( ChangeEvent e ) { public void stateChanged( ChangeEvent e ) {
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true )) if( eventQueuePushNotSupported || !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
return; return;
// handle menu selection change later, but only once in case of temporary changes // handle menu selection change later, but only once in case of temporary changes
@@ -173,8 +178,29 @@ debug*/
targetBottomY = popupLocation.y + popupSize.height; targetBottomY = popupLocation.y + popupSize.height;
// install own event queue to suppress mouse events when mouse is moved within safe triangle // install own event queue to suppress mouse events when mouse is moved within safe triangle
if( subMenuEventQueue == null ) if( subMenuEventQueue == null ) {
subMenuEventQueue = new SubMenuEventQueue(); SubMenuEventQueue queue = new SubMenuEventQueue();
try {
Toolkit toolkit = Toolkit.getDefaultToolkit();
toolkit.getSystemEventQueue().push( queue );
// check whether push() worked
// (e.g. SWTSwing uses own event queue that does not support push())
if( toolkit.getSystemEventQueue() != queue ) {
eventQueuePushNotSupported = true;
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", null );
return;
}
subMenuEventQueue = queue;
} catch( RuntimeException ex ) {
// catch runtime exception from EventQueue.push()
eventQueuePushNotSupported = true;
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", ex );
return;
}
}
// create safe triangle painter // create safe triangle painter
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) ) if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
@@ -247,8 +273,6 @@ debug*/
} }
} ); } );
timeoutTimer.setRepeats( false ); timeoutTimer.setRepeats( false );
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
} }
void uninstall() { void uninstall() {

View File

@@ -57,6 +57,8 @@ public abstract class FlatAbstractIcon
// g2.setColor( Color.blue ); // g2.setColor( Color.blue );
// g2.drawRect( x, y, getIconWidth() - 1, getIconHeight() - 1 ); // g2.drawRect( x, y, getIconWidth() - 1, getIconHeight() - 1 );
paintBackground( c, g2, x, y );
g2.translate( x, y ); g2.translate( x, y );
UIScale.scaleGraphics( g2 ); UIScale.scaleGraphics( g2 );
@@ -69,7 +71,11 @@ public abstract class FlatAbstractIcon
} }
} }
protected abstract void paintIcon( Component c, Graphics2D g2 ); /** @since 3.5.2 */
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
}
protected abstract void paintIcon( Component c, Graphics2D g );
@Override @Override
public int getIconWidth() { public int getIconWidth() {

View File

@@ -60,23 +60,24 @@ public abstract class FlatWindowAbstractIcon
@Override @Override
protected void paintIcon( Component c, Graphics2D g ) { protected void paintIcon( Component c, Graphics2D g ) {
paintBackground( c, g );
g.setColor( getForeground( c ) ); g.setColor( getForeground( c ) );
HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x ); HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x );
} }
protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ); protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
protected void paintBackground( Component c, Graphics2D g ) { /** @since 3.5.2 */
@Override
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground ); Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
if( background != null ) { if( background != null ) {
// disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%) // disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%)
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING ); Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF ); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
// fill background of whole component
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) ); g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
g.fillRect( 0, 0, width, height ); g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint ); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
} }

View File

@@ -19,13 +19,22 @@ package com.formdev.flatlaf.ui;
import java.awt.Color; import java.awt.Color;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import javax.swing.AbstractButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JToolTip;
import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document; import javax.swing.text.Document;
import javax.swing.text.LabelView; import javax.swing.text.LabelView;
import javax.swing.text.Style; import javax.swing.text.Style;
import javax.swing.text.StyleConstants; import javax.swing.text.StyleConstants;
import javax.swing.text.View; import javax.swing.text.View;
import javax.swing.text.html.CSS;
import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.StyleSheet; import javax.swing.text.html.StyleSheet;
@@ -42,7 +51,7 @@ public class FlatHTML
* which re-calculates font sizes based on current component font size. * which re-calculates font sizes based on current component font size.
* This is necessary for "absolute-size" keywords (e.g. "x-large") * This is necessary for "absolute-size" keywords (e.g. "x-large")
* for "font-size" attributes in default style sheet (see javax/swing/text/html/default.css). * for "font-size" attributes in default style sheet (see javax/swing/text/html/default.css).
* See also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size?retiredLocale=de#values">CSS font-size</a>. * See also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values">CSS font-size</a>.
* <p> * <p>
* This method should be invoked after {@link BasicHTML#updateRenderer(JComponent, String)}. * This method should be invoked after {@link BasicHTML#updateRenderer(JComponent, String)}.
*/ */
@@ -61,16 +70,86 @@ public class FlatHTML
// - if point size at index 7 is not 36, then probably HTML text contains BASE_SIZE rule // - if point size at index 7 is not 36, then probably HTML text contains BASE_SIZE rule
// - if point size at index 4 is equal to given font size, then it is not necessary to add BASE_SIZE rule // - if point size at index 4 is equal to given font size, then it is not necessary to add BASE_SIZE rule
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet(); StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
/*debug
for( int i = 1; i <= 7; i++ )
System.out.println( i+": "+ styleSheet.getPointSize( i ) );
debug*/
int fontBaseSize = c.getFont().getSize(); int fontBaseSize = c.getFont().getSize();
if( styleSheet.getPointSize( 7 ) != 36f || if( styleSheet.getPointSize( 7 ) != 36f ||
styleSheet.getPointSize( 4 ) == fontBaseSize ) styleSheet.getPointSize( 4 ) == fontBaseSize )
return; return;
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule() // check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
styleSheet.addRule( "BASE_SIZE " + fontBaseSize ); if( !usesAbsoluteSizeKeywordForFontSize( view ) )
clearViewCaches( view ); return;
// dumpViews( view, 0 ); // get HTML text from component
String text;
if( c instanceof JLabel )
text = ((JLabel)c).getText();
else if( c instanceof AbstractButton )
text = ((AbstractButton)c).getText();
else if( c instanceof JToolTip )
text = ((JToolTip)c).getTipText();
else
return;
if( text == null )
return;
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
String openTag = "";
String closeTag = "";
String lowerText = text.toLowerCase( Locale.ENGLISH );
int headIndex;
int styleIndex;
int insertIndex;
if( (headIndex = lowerText.indexOf( "<head>" )) >= 0 ) {
// there is a <head> tag --> insert after <head> tag
insertIndex = headIndex + "<head>".length();
} else if( (styleIndex = lowerText.indexOf( "<style>" )) >= 0 ) {
// there is a <style> tag --> insert before <style> tag
insertIndex = styleIndex;
} else {
// no <head> or <style> tag --> insert <head> tag after <html> tag
insertIndex = "<html>".length();
openTag = "<head>";
closeTag = "</head>";
}
String newText = text.substring( 0, insertIndex )
+ openTag + style + closeTag
+ text.substring( insertIndex );
BasicHTML.updateRenderer( c, newText );
}
private static final Set<String> absoluteSizeKeywordsSet = new HashSet<>( Arrays.asList(
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large" ) );
/**
* Checks whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
* (see javax/swing/text/html/default.css).
*/
private static boolean usesAbsoluteSizeKeywordForFontSize( View view ) {
AttributeSet attributes = view.getAttributes();
if( attributes != null ) {
Object fontSize = attributes.getAttribute( CSS.Attribute.FONT_SIZE );
if( fontSize != null ) {
if( absoluteSizeKeywordsSet.contains( fontSize.toString() ) )
return true;
}
}
int viewCount = view.getViewCount();
for( int i = 0; i < viewCount; i++ ) {
if( usesAbsoluteSizeKeywordForFontSize( view.getView( i ) ) )
return true;
}
return false;
} }
/** /**
@@ -128,8 +207,8 @@ public class FlatHTML
* updates the HTML view. * updates the HTML view.
*/ */
public static void propertyChange( PropertyChangeEvent e ) { public static void propertyChange( PropertyChangeEvent e ) {
if( BasicHTML.propertyKey.equals( e.getPropertyName() ) ) if( BasicHTML.propertyKey.equals( e.getPropertyName() ) && e.getNewValue() instanceof View )
FlatHTML.updateRendererCSSFontBaseSize( (JComponent) e.getSource() ); updateRendererCSSFontBaseSize( (JComponent) e.getSource() );
} }
/*debug /*debug
@@ -142,15 +221,27 @@ public class FlatHTML
public static void dumpViews( View view, int indent ) { public static void dumpViews( View view, int indent ) {
for( int i = 0; i < indent; i++ ) for( int i = 0; i < indent; i++ )
System.out.print( " " ); System.out.print( " " );
System.out.print( view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName() );
if( view instanceof LabelView ) { System.out.printf( "%s @%-8x %3d,%2d",
LabelView lview = ((LabelView)view); view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName(),
Font font = lview.getFont(); System.identityHashCode( view ),
Color foreground = lview.getForeground(); (int) view.getPreferredSpan( View.X_AXIS ),
System.out.printf( " %2d-%-2d %-14s %d #%06x", (int) view.getPreferredSpan( View.Y_AXIS ) );
lview.getStartOffset(), lview.getEndOffset() - 1,
font.getName(), font.getSize(), AttributeSet attrs = view.getAttributes();
foreground.getRGB() & 0xffffff ); if( attrs != null ) {
Object fontSize = attrs.getAttribute( CSS.Attribute.FONT_SIZE );
System.out.printf( " %-8s", fontSize );
}
if( view instanceof javax.swing.text.GlyphView ) {
javax.swing.text.GlyphView gview = ((javax.swing.text.GlyphView)view);
java.awt.Font font = gview.getFont();
System.out.printf( " %3d-%-3d %s %2d (@%x) #%06x '%s'",
gview.getStartOffset(), gview.getEndOffset() - 1,
font.getName(), font.getSize(), System.identityHashCode( font ),
gview.getForeground().getRGB() & 0xffffff,
gview.getText( gview.getStartOffset(), gview.getEndOffset() ) );
} }
System.out.println(); System.out.println();

View File

@@ -36,6 +36,8 @@ import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.WindowFocusListener; import java.awt.event.WindowFocusListener;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@@ -43,6 +45,7 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLayeredPane; import javax.swing.JLayeredPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -60,6 +63,7 @@ import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.BasicComboPopup;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -113,13 +117,7 @@ public class FlatPopupFactory
// macOS and Linux adds drop shadow to heavy weight popups // macOS and Linux adds drop shadow to heavy weight popups
if( SystemInfo.isMacOS || SystemInfo.isLinux ) { if( SystemInfo.isMacOS || SystemInfo.isLinux ) {
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents ); NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
if( popup.popupWindow != null && SystemInfo.isMacOS && if( popup.popupWindow != null && isMacOSBorderSupported() )
// do not use rounded border on macOS 14.4+ because it may freeze the application
// and crash the macOS WindowServer process (reports vary from Finder restarts to OS restarts)
// https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215
// https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442
SystemInfo.osVersion < SystemInfo.toVersion( 14, 4, 0, 0 ) &&
FlatNativeMacLibrary.isLoaded() )
setupRoundedBorder( popup.popupWindow, owner, contents ); setupRoundedBorder( popup.popupWindow, owner, contents );
return popup; return popup;
} }
@@ -139,7 +137,10 @@ public class FlatPopupFactory
forceHeavyWeight = true; forceHeavyWeight = true;
// create drop shadow popup // create drop shadow popup
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents ); Popup popupForScreenOfOwner = getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight );
return owner.getGraphicsConfiguration().isTranslucencyCapable()
? new DropShadowPopup( popupForScreenOfOwner, owner, contents )
: new NonFlashingPopup( popupForScreenOfOwner, owner, contents );
} }
/** /**
@@ -357,19 +358,29 @@ public class FlatPopupFactory
//---- native rounded border ---------------------------------------------- //---- native rounded border ----------------------------------------------
private static boolean isWindows11BorderSupported() { private static boolean isWindows11BorderSupported() {
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded(); return SystemInfo.isWindows_11_orLater &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
FlatNativeWindowsLibrary.isLoaded();
}
private static boolean isMacOSBorderSupported() {
// do not use rounded border on macOS 14.4+ because it may freeze the application
// and crash the macOS WindowServer process (reports vary from Finder restarts to OS restarts)
// https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215
// https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442
boolean isMacOS_14_4_orLater = (SystemInfo.osVersion >= SystemInfo.toVersion( 14, 4, 0, 0 ));
return SystemInfo.isMacOS &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, !isMacOS_14_4_orLater ) &&
FlatNativeMacLibrary.isLoaded();
} }
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) { private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) {
// make sure that the native window is created
if( !popupWindow.isDisplayable() )
popupWindow.addNotify();
int borderCornerRadius = getBorderCornerRadius( owner, contents ); int borderCornerRadius = getBorderCornerRadius( owner, contents );
float borderWidth = getRoundedBorderWidth( owner, contents ); float borderWidth = getRoundedBorderWidth( owner, contents );
// get Swing border color // get Swing border color
Color borderColor = null; // use system default color Color borderColor;
if( contents instanceof JComponent ) { if( contents instanceof JComponent ) {
Border border = ((JComponent)contents).getBorder(); Border border = ((JComponent)contents).getBorder();
border = FlatUIUtils.unwrapNonUIResourceBorder( border ); border = FlatUIUtils.unwrapNonUIResourceBorder( border );
@@ -381,11 +392,33 @@ public class FlatPopupFactory
borderColor = ((LineBorder)border).getLineColor(); borderColor = ((LineBorder)border).getLineColor();
else if( border instanceof EmptyBorder ) else if( border instanceof EmptyBorder )
borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
else
borderColor = null; // use system default color
// avoid that FlatLineBorder paints the Swing border // avoid that FlatLineBorder paints the Swing border
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true ); ((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true );
} } else
borderColor = null; // use system default color
if( popupWindow.isDisplayable() ) {
// native window already created
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor );
} else {
// native window not yet created --> add listener to set native border after window creation
AtomicReference<HierarchyListener> l = new AtomicReference<>();
l.set( e -> {
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
(e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 )
{
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor );
popupWindow.removeHierarchyListener( l.get() );
}
} );
popupWindow.addHierarchyListener( l.get() );
}
}
private static void setupRoundedBorderImpl( Window popupWindow, int borderCornerRadius, float borderWidth, Color borderColor ) {
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
// get native window handle // get native window handle
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow ); long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );

View File

@@ -448,6 +448,11 @@ public class FlatRootPaneUI
titlePane.titleBarColorsChanged(); titlePane.titleBarColorsChanged();
break; break;
case FlatClientProperties.TITLE_BAR_HEIGHT:
if( titlePane != null )
titlePane.revalidate();
break;
case FlatClientProperties.FULL_WINDOW_CONTENT: case FlatClientProperties.FULL_WINDOW_CONTENT:
if( titlePane != null ) { if( titlePane != null ) {
rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() ); rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() );

View File

@@ -210,7 +210,7 @@ public class FlatScrollPaneUI
// Use (0, 0) view position to obtain a constant unit increment of first item. // Use (0, 0) view position to obtain a constant unit increment of first item.
// Unit increment may be different for each item. // Unit increment may be different for each item.
Rectangle visibleRect = new Rectangle( viewport.getViewSize() ); Rectangle visibleRect = new Rectangle( viewport.getExtentSize() );
unitIncrement = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 ); unitIncrement = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 );
if( unitIncrement > 0 ) { if( unitIncrement > 0 ) {

View File

@@ -1685,7 +1685,7 @@ debug*/
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false ); w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
// add gap for selected tab to path // add gap for selected tab to path
if( getTabType() == TAB_TYPE_CARD ) { if( getTabType() == TAB_TYPE_CARD && selectedIndex >= 0 ) {
float csh = scale( (float) contentSeparatorHeight ); float csh = scale( (float) contentSeparatorHeight );
Rectangle tabRect = getTabBounds( tabPane, selectedIndex ); Rectangle tabRect = getTabBounds( tabPane, selectedIndex );

View File

@@ -359,6 +359,10 @@ public class FlatTitlePane
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize(); Dimension size = super.getPreferredSize();
int titleBarHeight = clientPropertyInt( rootPane, TITLE_BAR_HEIGHT, -1 );
if( titleBarHeight >= 0 )
return new Dimension( size.width, UIScale.scale( titleBarHeight ) );
if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) { if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) {
// make title pane height smaller when frame is maximized // make title pane height smaller when frame is maximized
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) ); size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) );
@@ -395,6 +399,12 @@ public class FlatTitlePane
// allow the button to shrink if space is rare // allow the button to shrink if space is rare
return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height ); return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height );
} }
@Override
public Dimension getMaximumSize() {
// allow the button to fill whole button area height
// see also BasicMenuUI.getMaximumSize()
return new Dimension( super.getMaximumSize().width, Short.MAX_VALUE );
}
}; };
button.setFocusable( false ); button.setFocusable( false );
button.setContentAreaFilled( false ); button.setContentAreaFilled( false );
@@ -1079,7 +1089,7 @@ public class FlatTitlePane
} }
private boolean isTitleBarCaptionAt( Component c, int x, int y ) { private boolean isTitleBarCaptionAt( Component c, int x, int y ) {
if( !c.isDisplayable() || !c.isVisible() || !c.contains( x, y ) || c == mouseLayer ) if( !c.isDisplayable() || !c.isVisible() || !contains( c, x, y ) || c == mouseLayer )
return true; // continue checking with next component return true; // continue checking with next component
if( c.isEnabled() && if( c.isEnabled() &&
@@ -1131,6 +1141,16 @@ public class FlatTitlePane
return true; return true;
} }
/**
* Same as {@link Component#contains(int, int)}, but not using that method
* because it may be overridden by custom components and invoke code that
* tries to request AWT tree lock on 'AWT-Windows' thread.
* This could freeze the application if AWT tree is already locked on 'AWT-EventQueue' thread.
*/
private boolean contains( Component c, int x, int y ) {
return x >= 0 && y >= 0 && x < c.getWidth() && y < c.getHeight();
}
private int lastCaptionHitTestX; private int lastCaptionHitTestX;
private int lastCaptionHitTestY; private int lastCaptionHitTestY;
private long lastCaptionHitTestTime; private long lastCaptionHitTestTime;

View File

@@ -531,8 +531,11 @@ public class FlatToolBarUI
private Component getRecentComponent( Container aContainer, boolean first ) { private Component getRecentComponent( Container aContainer, boolean first ) {
// if moving focus into the toolbar, focus recently focused toolbar button // if moving focus into the toolbar, focus recently focused toolbar button
if( focusedCompIndex >= 0 && focusedCompIndex < toolBar.getComponentCount() ) if( focusedCompIndex >= 0 && focusedCompIndex < toolBar.getComponentCount() ) {
return toolBar.getComponent( focusedCompIndex ); Component c = toolBar.getComponent( focusedCompIndex );
if( accept( c ) )
return c;
}
return first return first
? super.getFirstComponent( aContainer ) ? super.getFirstComponent( aContainer )

View File

@@ -521,12 +521,12 @@ public class HiDPIUtils
int x2 = x + c.getX(); int x2 = x + c.getX();
int y2 = y + c.getY(); int y2 = y + c.getY();
for( Component p = c.getParent(); p != null; p = p.getParent() ) { for( Component p = c.getParent(); p != null; p = p.getParent() ) {
x2 += p.getX();
y2 += p.getY();
if( x2 + width < p.getWidth() && y2 + height < p.getHeight() && p instanceof JComponent ) { if( x2 + width < p.getWidth() && y2 + height < p.getHeight() && p instanceof JComponent ) {
callback.addDirtyRegion( (JComponent) p, x2, y2, width, height ); callback.addDirtyRegion( (JComponent) p, x2, y2, width, height );
return; return;
} }
x2 += p.getX();
y2 += p.getY();
} }
} }

View File

@@ -21,6 +21,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.demo.ScrollablePanel; import com.formdev.flatlaf.demo.ScrollablePanel;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
@@ -63,6 +64,15 @@ public class FlatOptionPaneTest
UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() ); UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() );
} }
private void showWithCustomIcon() {
JOptionPane optionPane = new JOptionPane( "Hello world." );
JDialog dialog = optionPane.createDialog( "With Custom Icon" );
dialog.getRootPane().putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, true );
dialog.setIconImage( new ImageIcon( FlatOptionPaneTest.class.getResource( "/com/formdev/flatlaf/testing/test32.png" ) ).getImage() );
dialog.setVisible( true );
dialog.dispose();
}
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
ScrollablePanel panel9 = new ScrollablePanel(); ScrollablePanel panel9 = new ScrollablePanel();
@@ -75,6 +85,7 @@ public class FlatOptionPaneTest
JPanel panel2 = new JPanel(); JPanel panel2 = new JPanel();
JOptionPane errorOptionPane = new JOptionPane(); JOptionPane errorOptionPane = new JOptionPane();
errorShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel(); errorShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel();
JButton showWithCustomIconButton = new JButton();
JLabel informationLabel = new JLabel(); JLabel informationLabel = new JLabel();
JPanel panel3 = new JPanel(); JPanel panel3 = new JPanel();
JOptionPane informationOptionPane = new JOptionPane(); JOptionPane informationOptionPane = new JOptionPane();
@@ -173,6 +184,11 @@ public class FlatOptionPaneTest
errorShowDialogLabel.setOptionPane(errorOptionPane); errorShowDialogLabel.setOptionPane(errorOptionPane);
panel9.add(errorShowDialogLabel, "cell 1 1"); panel9.add(errorShowDialogLabel, "cell 1 1");
//---- showWithCustomIconButton ----
showWithCustomIconButton.setText("Show with custom icon");
showWithCustomIconButton.addActionListener(e -> showWithCustomIcon());
panel9.add(showWithCustomIconButton, "cell 2 1");
//---- informationLabel ---- //---- informationLabel ----
informationLabel.setText("Information"); informationLabel.setText("Information");
panel9.add(informationLabel, "cell 0 2"); panel9.add(informationLabel, "cell 0 2");

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8" JFDML JFormDesigner: "8.2.3.0.386" Java: "21" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -83,6 +83,13 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1" "value": "cell 1 1"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showWithCustomIconButton"
"text": "Show with custom icon"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showWithCustomIcon", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "informationLabel" name: "informationLabel"
"text": "Information" "text": "Information"

View File

@@ -127,6 +127,9 @@ public class FlatWindowDecorationsTest
+ " @ " + bounds.x + ", " + bounds.y ); + " @ " + bounds.x + ", " + bounds.y );
} else } else
fullWindowContentButtonsBoundsField.setText( "null" ); fullWindowContentButtonsBoundsField.setText( "null" );
fullWindowContentButtonsBoundsLabel.setEnabled( bounds != null );
fullWindowContentButtonsBoundsField.setEnabled( bounds != null );
} ); } );
} }
} }
@@ -189,6 +192,7 @@ public class FlatWindowDecorationsTest
if( rightCompCheckBox.isSelected() ) { if( rightCompCheckBox.isSelected() ) {
rightStretchCompCheckBox.setSelected( false ); rightStretchCompCheckBox.setSelected( false );
tallCompCheckBox.setSelected( false );
JButton myButton = new JButton( "?" ); JButton myButton = new JButton( "?" );
myButton.putClientProperty( "JButton.buttonType", "toolBarButton" ); myButton.putClientProperty( "JButton.buttonType", "toolBarButton" );
@@ -207,6 +211,7 @@ public class FlatWindowDecorationsTest
if( rightStretchCompCheckBox.isSelected() ) { if( rightStretchCompCheckBox.isSelected() ) {
rightCompCheckBox.setSelected( false ); rightCompCheckBox.setSelected( false );
tallCompCheckBox.setSelected( false );
menuBar.add( Box.createGlue() ); menuBar.add( Box.createGlue() );
menuBar.add( new JProgressBar() ); menuBar.add( new JProgressBar() );
@@ -216,6 +221,20 @@ public class FlatWindowDecorationsTest
menuBar.repaint(); menuBar.repaint();
} }
private void tallCompChanged() {
removeNonMenusFromMenuBar();
if( tallCompCheckBox.isSelected() ) {
rightCompCheckBox.setSelected( false );
rightStretchCompCheckBox.setSelected( false );
menuBar.add( new JButton( "<html>large<br>button<br>large<br>button</html>" ) );
}
menuBar.revalidate();
menuBar.repaint();
}
private void removeNonMenusFromMenuBar() { private void removeNonMenusFromMenuBar() {
Component[] components = menuBar.getComponents(); Component[] components = menuBar.getComponents();
for( int i = components.length - 1; i >= 0; i-- ) { for( int i = components.length - 1; i >= 0; i-- ) {
@@ -546,6 +565,16 @@ debug*/
} }
} }
private void titleBarHeightChanged() {
JRootPane rootPane = getWindowRootPane();
if( rootPane != null ) {
boolean enabled = titleBarHeightCheckBox.isSelected();
titleBarHeightField.setEnabled( enabled );
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_HEIGHT, enabled ? titleBarHeightField.getValue() : null );
}
}
private JRootPane getWindowRootPane() { private JRootPane getWindowRootPane() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
return (window instanceof RootPaneContainer) return (window instanceof RootPaneContainer)
@@ -572,12 +601,14 @@ debug*/
maximizedBoundsCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox();
JPanel panel4 = new JPanel(); JPanel panel4 = new JPanel();
showIconCheckBox = new FlatTriStateCheckBox(); showIconCheckBox = new FlatTriStateCheckBox();
titleBarHeightCheckBox = new JCheckBox();
showTitleCheckBox = new JCheckBox(); showTitleCheckBox = new JCheckBox();
titleBarHeightField = new JSpinner();
showIconifyCheckBox = new JCheckBox(); showIconifyCheckBox = new JCheckBox();
showMaximizeCheckBox = new JCheckBox(); showMaximizeCheckBox = new JCheckBox();
showCloseCheckBox = new JCheckBox(); showCloseCheckBox = new JCheckBox();
fullWindowContentCheckBox = new JCheckBox(); fullWindowContentCheckBox = new JCheckBox();
JLabel fullWindowContentButtonsBoundsLabel = new JLabel(); fullWindowContentButtonsBoundsLabel = new JLabel();
fullWindowContentButtonsBoundsField = new JLabel(); fullWindowContentButtonsBoundsField = new JLabel();
JPanel panel6 = new JPanel(); JPanel panel6 = new JPanel();
menuBarCheckBox = new JCheckBox(); menuBarCheckBox = new JCheckBox();
@@ -585,6 +616,7 @@ debug*/
menuBarVisibleCheckBox = new JCheckBox(); menuBarVisibleCheckBox = new JCheckBox();
rightCompCheckBox = new JCheckBox(); rightCompCheckBox = new JCheckBox();
rightStretchCompCheckBox = new JCheckBox(); rightStretchCompCheckBox = new JCheckBox();
tallCompCheckBox = new JCheckBox();
JPanel panel3 = new JPanel(); JPanel panel3 = new JPanel();
addMenuButton = new JButton(); addMenuButton = new JButton();
addGlueButton = new JButton(); addGlueButton = new JButton();
@@ -660,7 +692,8 @@ debug*/
"[fill]" + "[fill]" +
"[fill]" + "[fill]" +
"[]" + "[]" +
"[]")); "[]" +
"[40]"));
//======== panel7 ======== //======== panel7 ========
{ {
@@ -711,7 +744,8 @@ debug*/
panel4.setLayout(new MigLayout( panel4.setLayout(new MigLayout(
"ltr,hidemode 3,gap 0 0", "ltr,hidemode 3,gap 0 0",
// columns // columns
"[grow,left]", "[grow,left]" +
"[fill]",
// rows // rows
"[]" + "[]" +
"[]" + "[]" +
@@ -726,12 +760,23 @@ debug*/
showIconCheckBox.addActionListener(e -> showIconChanged()); showIconCheckBox.addActionListener(e -> showIconChanged());
panel4.add(showIconCheckBox, "cell 0 0"); panel4.add(showIconCheckBox, "cell 0 0");
//---- titleBarHeightCheckBox ----
titleBarHeightCheckBox.setText("Height:");
titleBarHeightCheckBox.addActionListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightCheckBox, "cell 1 0");
//---- showTitleCheckBox ---- //---- showTitleCheckBox ----
showTitleCheckBox.setText("show title"); showTitleCheckBox.setText("show title");
showTitleCheckBox.setSelected(true); showTitleCheckBox.setSelected(true);
showTitleCheckBox.addActionListener(e -> showTitleChanged()); showTitleCheckBox.addActionListener(e -> showTitleChanged());
panel4.add(showTitleCheckBox, "cell 0 1"); panel4.add(showTitleCheckBox, "cell 0 1");
//---- titleBarHeightField ----
titleBarHeightField.setEnabled(false);
titleBarHeightField.setModel(new SpinnerNumberModel(44, null, null, 2));
titleBarHeightField.addChangeListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightField, "cell 1 1");
//---- showIconifyCheckBox ---- //---- showIconifyCheckBox ----
showIconifyCheckBox.setText("show iconfiy"); showIconifyCheckBox.setText("show iconfiy");
showIconifyCheckBox.setSelected(true); showIconifyCheckBox.setSelected(true);
@@ -757,10 +802,12 @@ debug*/
//---- fullWindowContentButtonsBoundsLabel ---- //---- fullWindowContentButtonsBoundsLabel ----
fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:"); fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:");
fullWindowContentButtonsBoundsLabel.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6");
//---- fullWindowContentButtonsBoundsField ---- //---- fullWindowContentButtonsBoundsField ----
fullWindowContentButtonsBoundsField.setText("null"); fullWindowContentButtonsBoundsField.setText("null");
fullWindowContentButtonsBoundsField.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6");
} }
add(panel4, "cell 1 0"); add(panel4, "cell 1 0");
@@ -777,6 +824,7 @@ debug*/
"[]" + "[]" +
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]")); "[]"));
//---- menuBarCheckBox ---- //---- menuBarCheckBox ----
@@ -806,6 +854,11 @@ debug*/
rightStretchCompCheckBox.setText("right aligned stretching component"); rightStretchCompCheckBox.setText("right aligned stretching component");
rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged()); rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged());
panel6.add(rightStretchCompCheckBox, "cell 0 4"); panel6.add(rightStretchCompCheckBox, "cell 0 4");
//---- tallCompCheckBox ----
tallCompCheckBox.setText("tall component");
tallCompCheckBox.addActionListener(e -> tallCompChanged());
panel6.add(tallCompCheckBox, "cell 0 5");
} }
add(panel6, "cell 2 0"); add(panel6, "cell 2 0");
@@ -1243,17 +1296,21 @@ debug*/
private JCheckBox fullScreenCheckBox; private JCheckBox fullScreenCheckBox;
private JCheckBox maximizedBoundsCheckBox; private JCheckBox maximizedBoundsCheckBox;
private FlatTriStateCheckBox showIconCheckBox; private FlatTriStateCheckBox showIconCheckBox;
private JCheckBox titleBarHeightCheckBox;
private JCheckBox showTitleCheckBox; private JCheckBox showTitleCheckBox;
private JSpinner titleBarHeightField;
private JCheckBox showIconifyCheckBox; private JCheckBox showIconifyCheckBox;
private JCheckBox showMaximizeCheckBox; private JCheckBox showMaximizeCheckBox;
private JCheckBox showCloseCheckBox; private JCheckBox showCloseCheckBox;
private JCheckBox fullWindowContentCheckBox; private JCheckBox fullWindowContentCheckBox;
private JLabel fullWindowContentButtonsBoundsLabel;
private JLabel fullWindowContentButtonsBoundsField; private JLabel fullWindowContentButtonsBoundsField;
private JCheckBox menuBarCheckBox; private JCheckBox menuBarCheckBox;
private JCheckBox menuBarEmbeddedCheckBox; private JCheckBox menuBarEmbeddedCheckBox;
private JCheckBox menuBarVisibleCheckBox; private JCheckBox menuBarVisibleCheckBox;
private JCheckBox rightCompCheckBox; private JCheckBox rightCompCheckBox;
private JCheckBox rightStretchCompCheckBox; private JCheckBox rightStretchCompCheckBox;
private JCheckBox tallCompCheckBox;
private JButton addMenuButton; private JButton addMenuButton;
private JButton addGlueButton; private JButton addGlueButton;
private JButton addCaptionButton; private JButton addCaptionButton;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.2.1.0.348" Java: "21.0.1" encoding: "UTF-8" JFDML JFormDesigner: "8.2.3.0.386" Java: "21" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left][fill][fill][fill]" "$columnConstraints": "[left][fill][fill][fill]"
"$rowConstraints": "[fill][fill][][]" "$rowConstraints": "[fill][fill][][][40]"
} ) { } ) {
name: "this" name: "this"
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
@@ -76,7 +76,7 @@ new FormModel {
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,hidemode 3,gap 0 0" "$layoutConstraints": "ltr,hidemode 3,gap 0 0"
"$columnConstraints": "[grow,left]" "$columnConstraints": "[grow,left][fill]"
"$rowConstraints": "[][][][][]rel[]rel[]" "$rowConstraints": "[][][][][]rel[]rel[]"
} ) { } ) {
name: "panel4" name: "panel4"
@@ -91,6 +91,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0" "value": "cell 0 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "titleBarHeightCheckBox"
"text": "Height:"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "titleBarHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTitleCheckBox" name: "showTitleCheckBox"
"text": "show title" "text": "show title"
@@ -102,6 +112,20 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1" "value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "titleBarHeightField"
"enabled": false
"model": new javax.swing.SpinnerNumberModel {
stepSize: 2
value: 44
}
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "titleBarHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showIconifyCheckBox" name: "showIconifyCheckBox"
"text": "show iconfiy" "text": "show iconfiy"
@@ -148,12 +172,17 @@ new FormModel {
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fullWindowContentButtonsBoundsLabel" name: "fullWindowContentButtonsBoundsLabel"
"text": "Buttons bounds:" "text": "Buttons bounds:"
"enabled": false
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6" "value": "cell 0 6"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fullWindowContentButtonsBoundsField" name: "fullWindowContentButtonsBoundsField"
"text": "null" "text": "null"
"enabled": false
auxiliary() { auxiliary() {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
@@ -166,7 +195,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,hidemode 3,gap 0 0" "$layoutConstraints": "ltr,hidemode 3,gap 0 0"
"$columnConstraints": "[left]" "$columnConstraints": "[left]"
"$rowConstraints": "[][][][][]" "$rowConstraints": "[][][][][][]"
} ) { } ) {
name: "panel6" name: "panel6"
"border": new javax.swing.border.TitledBorder( "Menu Bar" ) "border": new javax.swing.border.TitledBorder( "Menu Bar" )
@@ -223,6 +252,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4" "value": "cell 0 4"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "tallCompCheckBox"
"text": "tall component"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tallCompChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0" "value": "cell 2 0"
} ) } )
@@ -600,7 +639,7 @@ new FormModel {
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 960, 495 ) "size": new java.awt.Dimension( 960, 570 )
} ) } )
add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) { add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
name: "menuBar" name: "menuBar"
@@ -766,23 +805,23 @@ new FormModel {
} ) } )
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 515 ) "location": new java.awt.Point( 0, 585 )
"size": new java.awt.Dimension( 255, 30 ) "size": new java.awt.Dimension( 255, 30 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "styleButtonGroup" name: "styleButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 565 ) "location": new java.awt.Point( 0, 635 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "iconButtonGroup" name: "iconButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 615 ) "location": new java.awt.Point( 0, 685 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "typeButtonGroup" name: "typeButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 669 ) "location": new java.awt.Point( 0, 740 )
} ) } )
} }
} }

View File

@@ -14,7 +14,7 @@
# limitations under the License. # limitations under the License.
# #
flatlaf.releaseVersion = 3.5 flatlaf.releaseVersion = 3.5.2
flatlaf.developmentVersion = 3.6-SNAPSHOT flatlaf.developmentVersion = 3.6-SNAPSHOT
org.gradle.parallel = true org.gradle.parallel = true

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

7
gradlew vendored
View File

@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum

2
gradlew.bat vendored
View File

@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################

Binary file not shown.

BIN
images/none-sponsors.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB