Compare commits

...

48 Commits
1.1 ... 1.1.2

Author SHA1 Message Date
Karl Tauber
5729c20386 release 1.1.2 2021-04-07 11:53:18 +02:00
Karl Tauber
a4d70d8095 FlatTextComponentsTest: fixed compiler warnings (for previous commit) 2021-04-07 10:34:11 +02:00
Karl Tauber
8fcce349d5 ComboBox and Spinner: fixed too wide arrow button if component is higher than preferred (issue #302) 2021-04-07 01:39:29 +02:00
Karl Tauber
5a94676a3a Merge pull request #269 from SchiopuMatei/main
Added option for downscaling
2021-04-07 00:24:18 +02:00
Karl Tauber
f32d72ee62 UIScale:
- allow scale factors less than 100% for system property `flatlaf.uiScale`
- no longer round scale factor of system property `flatlaf.uiScale` to 1/4
- renamed system property `flatlaf.uiDowncale.enabled` to `flatlaf.uiScale.allowScaleDown`
- round smaller scale factors to 1/10
- absolute minimum user scale factor is now 0.1
2021-04-07 00:21:15 +02:00
Karl Tauber
e35fc8620c JIDE: fixed null font in other Lafs if (wrongly) using LookAndFeelFactory.addUIDefaultsInitializer() or LookAndFeelFactory.addUIDefaultsCustomizer() (issue #288) 2021-04-06 18:35:48 +02:00
Karl Tauber
277c288952 IntelliJ Themes: fixed system colors 2021-04-06 11:29:55 +02:00
Karl Tauber
240b08e55c IntelliJ Themes: fixed window title bar background if unified background is enabled 2021-04-06 11:04:52 +02:00
Karl Tauber
fe7f345661 Native window decorations: support changing title bar background and foreground colors per window (via client property) also if unified window title bar is enabled 2021-04-06 10:46:28 +02:00
Karl Tauber
c8db01c958 SplitPane: fixed JSplitPane.setContinuousLayout(false) (issue #301) 2021-04-05 14:24:49 +02:00
Karl Tauber
f456185f7d Native window decorations: support changing title bar background and foreground colors per window (via client property) 2021-04-05 14:19:41 +02:00
Karl Tauber
801b555835 Window decorations: fixed random window title bar background for unified backgrounds in cases were background is not filled by custom window/rootpane components (issue #254) 2021-04-04 11:47:15 +02:00
Karl Tauber
eee177e64b Window decorations: enabling/disabling menu bar embedding via system and client properties now works the same way as for window decorations
(previously it was only possible to disable menu bar embedding)
2021-04-03 16:19:11 +02:00
Karl Tauber
63639f8e96 Native window decorations: cleaned-up/simplified JetBrains Runtime custom window decorations "enabled" checking:
- `FlatSystemProperties.USE_WINDOW_DECORATIONS` is now also used for JBR custom window decorations
- `FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS` is now only used to disable JBR custom window decorations; then FlatLaf native window decorations are used
- JBR custom window decorations are now disabled when running in JetBrains Projector, Webswing or WinPE
2021-04-03 13:32:46 +02:00
Karl Tauber
de1b0b1bb6 MenuBar: do not use TitlePane.unifiedBackground if window decorations are disabled for the window 2021-04-03 11:51:45 +02:00
Karl Tauber
bbdd7fc2b4 Demo:
- keep "Options > Window decorations" selected for JetBrains Runtime
- disable "Options > Use underline menu selection" on macOS
- added font size `11`
2021-04-03 11:49:57 +02:00
Karl Tauber
6addb5c4b4 Native window decorations:
- API to check whether current platform supports window decorations `FlatLaf.supportsNativeWindowDecorations()`
- API to toggle window decorations of all windows `FlatLaf.setUseNativeWindowDecorations(boolean)`
- `FlatClientProperties.USE_WINDOW_DECORATIONS` can now used to toggle window decorations for single window
- cleaned-up/fixed/simplified window decorations "enabled" checking:
  1. if `FlatSystemProperties.USE_WINDOW_DECORATIONS` is set, its value is used
  2. if `FlatClientProperties.USE_WINDOW_DECORATIONS` is set, its value is used
  3. use value of UI default `TitlePane.useWindowDecorations`
2021-04-03 11:13:57 +02:00
Karl Tauber
b47e0c88d6 Merge pull request #298 from Bios-Marcel/fix-demo-menu-item-states
Fix selected states for native window border related menu items
2021-04-02 16:13:36 +02:00
Marcel Schramm
d06993d940 Add comment explaining why the use of JBR results in not having custom decorations 2021-04-01 22:14:39 +02:00
Karl Tauber
d31f167b9e TabbedPane: fixed NPE when creating/modifying in another thread (issue #299) 2021-04-01 12:35:50 +02:00
Karl Tauber
f12ee6c167 added dummy class to empty opend module packages 2021-04-01 09:40:22 +02:00
Karl Tauber
983b341f33 Native window decorations: fixed loading of native library when using JPMS for application (issue #289) 2021-04-01 01:07:35 +02:00
Karl Tauber
f3e6642f05 Button and ToggleButton: simplified/unified code of FlatButtonUI.getBackground() (issue #292) 2021-03-31 23:14:45 +02:00
Karl Tauber
0a63990d21 Button and ToggleButton: do not paint background of disabled (and unselected) toolBar buttons (issue #292; regression since fixing #112) 2021-03-31 22:28:43 +02:00
Karl Tauber
6909bb4b03 Native window decorations: removed superfluous pixel-line at top of screen when window is maximized (issue #296) 2021-03-31 20:56:17 +02:00
Marcel Schramm
620aa8bcee Fix selected states for native window border related menu items
The menu items for custom window decorations and embeded menu bar aren't selected anymore if the feature isn't supported.
On top of that, there's now a tooltip indicating that these aren't supported.
2021-03-31 19:59:29 +02:00
Karl Tauber
d13ddeb944 use larger font when running on WinPE (issue #279) 2021-03-30 11:00:27 +02:00
Karl Tauber
1b5da0e1d1 Window decorations: support enabling/disabling unified title bar backgrounds at runtime without FlatLaf.updateUI() 2021-03-30 01:34:34 +02:00
Karl Tauber
7a2d0e7fcb fixed crash when running in Webswing (issue #290) 2021-03-30 01:06:30 +02:00
Karl Tauber
477c3b6b1e README.md: added link to FlatLaf 1.0 announcement on Reddit 2021-03-28 18:44:21 +02:00
Karl Tauber
95312c3650 release 1.1.1 2021-03-28 16:04:14 +02:00
Karl Tauber
9006e835c6 natives.yml: exclude ~/.gradle/caches/modules-2/modules-2.lock from Gradle cache 2021-03-26 21:52:28 +01:00
Karl Tauber
f801d61929 support running on WinPE (issue #279) 2021-03-26 21:51:11 +01:00
Karl Tauber
a143e5777c Extras: FlatInspector: fixed InaccessibleObjectException when running in Java 16 2021-03-26 21:44:41 +01:00
Karl Tauber
bf500e46e7 Window decorations: fixed wrong/missing window icon when application replaces InternalFrame.icon (issue #284) 2021-03-25 16:14:41 +01:00
Karl Tauber
4a2f79f390 Native window decorations: updated DLLs (issues #282 and #283)
built by GitHub Actions:
https://github.com/JFormDesigner/FlatLaf/actions/runs/686023039
2021-03-25 11:10:13 +01:00
Karl Tauber
c24ce7c5bc Native window decorations: fixed broken maximizing window when restoring frame state at startup (issue #283) 2021-03-25 10:32:24 +01:00
Karl Tauber
8a6a0c7971 Native window decorations: fixed missing animations when minimizing, maximizing or restoring a window using window title bar buttons (issue #282) 2021-03-24 23:59:59 +01:00
Karl Tauber
de6e5bd800 fixed missing focus indicators in heavy-weight popups (issue #273) 2021-03-24 11:43:06 +01:00
Karl Tauber
e18a04f9e6 Merge pull request #278 from ingokegel/native_provider_setter
Add a setter for the native provider
2021-03-24 11:34:22 +01:00
Karl Tauber
14fc652f4b Window decorations: fixed right aligned progress bar in embedded menu bar was overlapping window title (issue #272) 2021-03-23 19:23:18 +01:00
Ingo Kegel
9a876e747a Added setter for native provider
This makes it possible to support situations where the extraction of a DLL at runtime is not possible
2021-03-23 16:47:08 +01:00
Karl Tauber
f8ee8b27fb InternalFrame: fixed translucent internal frame menu bar background if TitlePane.unifiedBackground is true (issue #274) 2021-03-23 15:08:01 +01:00
Karl Tauber
ce1a1487aa support menu bars in JDialog 2021-03-23 14:58:53 +01:00
Karl Tauber
fe1e364a1d Native window decorations: support disabling native window decorations per window via client property (issue #277) 2021-03-23 13:18:07 +01:00
Karl Tauber
eabb052107 Native window decorations: fixed double window title bar when first disposing a window and then showing it again (issue #277) 2021-03-23 10:07:43 +01:00
Karl Tauber
734f3621f1 Window decorations: Fixed NPE in FlatTitlePane.findHorizontalGlue() (issue #275) 2021-03-22 18:47:53 +01:00
SchiopuMatei
ed91aa4648 Added option for downscaling 2021-03-15 20:41:40 +02:00
48 changed files with 1249 additions and 361 deletions

View File

@@ -41,7 +41,9 @@ jobs:
- name: Cache Gradle cache
uses: actions/cache@v2
with:
path: ~/.gradle/caches
path: |
~/.gradle/caches
!~/.gradle/caches/modules-2/modules-2.lock
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle

View File

@@ -1,6 +1,68 @@
FlatLaf Change Log
==================
## 1.1.2
#### New features and improvements
- Native window decorations: Added API to check whether current platform
supports window decorations (`FlatLaf.supportsNativeWindowDecorations()`) and
to toggle window decorations of all windows
(`FlatLaf.setUseNativeWindowDecorations(boolean)`).
- Native window decorations: Support changing title bar background and
foreground colors per window. (set client properties
`JRootPane.titleBarBackground` and `JRootPane.titleBarForeground` on root pane
to a `java.awt.Color`).
#### Fixed bugs
- Native window decorations: Fixed loading of native library when using Java
Platform Module System (JPMS) for application. (issue #289)
- Native window decorations: Removed superfluous pixel-line at top of screen
when window is maximized. (issue #296)
- Window decorations: Fixed random window title bar background in cases were
background is not filled by custom window or root pane components and unified
background is enabled.
- IntelliJ Themes: Fixed window title bar background if unified background is
enabled.
- IntelliJ Themes: Fixed system colors.
- Button and ToggleButton: Do not paint background of disabled (and unselected)
toolBar buttons. (issue #292; regression since fixing #112)
- ComboBox and Spinner: Fixed too wide arrow button if component is higher than
preferred. (issue #302)
- SplitPane: `JSplitPane.setContinuousLayout(false)` did not work. (issue #301)
- TabbedPane: Fixed NPE when creating/modifying in another thread. (issue #299)
- Fixed crash when running in Webswing. (issue #290)
## 1.1.1
#### New features and improvements
- Native window decorations: Support disabling native window decorations per
window. (set client property `JRootPane.useWindowDecorations` on root pane to
`false`).
- Support running on WinPE. (issue #279)
#### Fixed bugs
- Native window decorations: Fixed missing animations when minimizing,
maximizing or restoring a window using window title bar buttons. (issue #282)
- Native window decorations: Fixed broken maximizing window when restoring frame
state at startup. (issue #283)
- Native window decorations: Fixed double window title bar when first disposing
a window with `frame.dispose()` and then showing it again with
`frame.setVisible(true)`. (issue #277)
- Custom window decorations: Fixed NPE in `FlatTitlePane.findHorizontalGlue()`.
(issue #275)
- Custom window decorations: Fixed right aligned progress bar in embedded menu
bar was overlapping window title. (issue #272)
- Fixed missing focus indicators in heavy-weight popups. (issue #273)
- InternalFrame: Fixed translucent internal frame menu bar background if
`TitlePane.unifiedBackground` is `true`. (issue #274)
- Extras: UI Inspector: Fixed `InaccessibleObjectException` when running in Java 16.
## 1.1
#### New features and improvements

View File

@@ -104,6 +104,7 @@ Buzz
----
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
val releaseVersion = "1.1"
val releaseVersion = "1.1.2"
val developmentVersion = "1.2-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion

View File

@@ -232,14 +232,63 @@ public interface FlatClientProperties
//---- JRootPane ----------------------------------------------------------
/**
* Specifies whether the menu bar is embedded into the title pane if custom
* window decorations are enabled. Default is {@code true}.
* Specifies whether FlatLaf native window decorations should be used
* for {@code JFrame} or {@code JDialog}.
* <p>
* Setting this enables/disables using FlatLaf native window decorations
* for the window that contains the root pane.
* <p>
* This client property has lower priority than system property
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
* than UI default {@code TitlePane.useWindowDecorations}.
* <p>
* (requires Window 10)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @since 1.1.1
*/
String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations";
/**
* Specifies whether the menu bar is embedded into the window title pane
* if window decorations are enabled.
* <p>
* Setting this enables/disables embedding
* for the window that contains the root pane.
* <p>
* This client property has lower priority than system property
* {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority
* than UI default {@code TitlePane.menuBarEmbedded}.
* <p>
* (requires Window 10)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
/**
* Background color of window title bar (requires enabled window decorations).
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color}
*
* @since 1.1.2
*/
String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground";
/**
* Foreground color of window title bar (requires enabled window decorations).
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color}
*
* @since 1.1.2
*/
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
//---- JScrollBar / JScrollPane -------------------------------------------
/**

View File

@@ -46,6 +46,7 @@ import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.LookAndFeel;
import javax.swing.PopupFactory;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIDefaults.ActiveValue;
@@ -59,6 +60,7 @@ import javax.swing.text.StyleContext;
import javax.swing.text.html.HTMLEditorKit;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
import com.formdev.flatlaf.ui.FlatPopupFactory;
import com.formdev.flatlaf.ui.FlatRootPaneUI;
import com.formdev.flatlaf.util.GrayFilter;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
@@ -157,7 +159,7 @@ public abstract class FlatLaf
*/
@Override
public boolean getSupportsWindowDecorations() {
if( SystemInfo.isProjector )
if( SystemInfo.isProjector || SystemInfo.isWebswing || SystemInfo.isWinPE )
return false;
if( SystemInfo.isWindows_10_orLater &&
@@ -377,6 +379,12 @@ public abstract class FlatLaf
initIconColors( defaults, isDark() );
FlatInputMaps.initInputMaps( defaults );
// copy InternalFrame.icon (the Java cup) to TitlePane.icon
// (using defaults.remove() to avoid that lazy value is resolved and icon loaded here)
Object icon = defaults.remove( "InternalFrame.icon" );
defaults.put( "InternalFrame.icon", icon );
defaults.put( "TitlePane.icon", icon );
// get addons and sort them by priority
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
List<FlatDefaultsAddon> addons = new ArrayList<>();
@@ -438,8 +446,16 @@ public abstract class FlatLaf
if( SystemInfo.isWindows ) {
Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" );
if( winFont != null )
uiFont = createCompositeFont( winFont.getFamily(), winFont.getStyle(), winFont.getSize() );
if( winFont != null ) {
if( SystemInfo.isWinPE ) {
// on WinPE use "win.defaultGUI.font", which is usually Tahoma,
// because Segoe UI font is not available on WinPE
Font winPEFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.defaultGUI.font" );
if( winPEFont != null )
uiFont = createCompositeFont( winPEFont.getFamily(), winPEFont.getStyle(), winFont.getSize() );
} else
uiFont = createCompositeFont( winFont.getFamily(), winFont.getStyle(), winFont.getSize() );
}
} else if( SystemInfo.isMacOS ) {
String fontName;
@@ -701,6 +717,79 @@ public abstract class FlatLaf
} );
}
/**
* Returns whether native window decorations are supported on current platform.
* <p>
* This requires Windows 10, but may be disabled if running in special environments
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
* {@code false}, then this method also returns {@code false}.
*
* @since 1.1.2
*/
public static boolean supportsNativeWindowDecorations() {
return SystemInfo.isWindows_10_orLater && FlatNativeWindowBorder.isSupported();
}
/**
* Returns whether native window decorations are enabled.
*
* @since 1.1.2
*/
public static boolean isUseNativeWindowDecorations() {
return UIManager.getBoolean( "TitlePane.useWindowDecorations" );
}
/**
* Sets whether native window decorations are enabled.
* <p>
* Existing frames and dialogs will be updated.
*
* @since 1.1.2
*/
public static void setUseNativeWindowDecorations( boolean enabled ) {
UIManager.put( "TitlePane.useWindowDecorations", enabled );
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) )
return;
// update existing frames and dialogs
for( Window w : Window.getWindows() ) {
if( isDisplayableFrameOrDialog( w ) )
FlatRootPaneUI.updateNativeWindowBorder( ((RootPaneContainer)w).getRootPane() );
}
}
/**
* Revalidate and repaint all displayable frames and dialogs.
*
* @since 1.1.2
*/
public static void revalidateAndRepaintAllFramesAndDialogs() {
for( Window w : Window.getWindows() ) {
if( isDisplayableFrameOrDialog( w ) ) {
w.revalidate();
w.repaint();
}
}
}
/**
* Repaint all displayable frames and dialogs.
*
* @since 1.1.2
*/
public static void repaintAllFramesAndDialogs() {
for( Window w : Window.getWindows() ) {
if( isDisplayableFrameOrDialog( w ) )
w.repaint();
}
}
private static boolean isDisplayableFrameOrDialog( Window w ) {
return w.isDisplayable() && (w instanceof JFrame || w instanceof JDialog);
}
public static boolean isShowMnemonics() {
return MnemonicHandler.isShowMnemonics();
}
@@ -744,6 +833,10 @@ public abstract class FlatLaf
public Object createValue( UIDefaults table ) {
Font defaultFont = UIManager.getFont( "defaultFont" );
// fallback (to avoid NPE in case that this is used in another Laf)
if( defaultFont == null )
defaultFont = UIManager.getFont( "Label.font" );
if( lastDefaultFont != defaultFont ) {
lastDefaultFont = defaultFont;

View File

@@ -16,6 +16,8 @@
package com.formdev.flatlaf;
import com.formdev.flatlaf.util.UIScale;
/**
* Defines/documents own system properties used in FlatLaf.
*
@@ -32,6 +34,8 @@ public interface FlatSystemProperties
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
* which has the same syntax as this one.
* <p>
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
* <p>
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
*/
String UI_SCALE = "flatlaf.uiScale";
@@ -44,6 +48,17 @@ public interface FlatSystemProperties
*/
String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled";
/**
* Specifies whether values smaller than 100% are allowed for the user scale factor
* (see {@link UIScale#getUserScaleFactor()}).
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> {@code false}
*
* @since 1.1.2
*/
String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown";
/**
* Specifies whether Ubuntu font should be used on Ubuntu Linux.
* By default, if not running in a JetBrains Runtime, the Liberation Sans font
@@ -55,13 +70,16 @@ public interface FlatSystemProperties
String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont";
/**
* Specifies whether FlatLaf native window decorations should be used
* Specifies whether native window decorations should be used
* when creating {@code JFrame} or {@code JDialog}.
* <p>
* Setting this to {@code true} forces using FlatLaf native window decorations
* even if they are not enabled by the application.
* Setting this to {@code true} forces using native window decorations
* even if they are not enabled by the application.<br>
* Setting this to {@code false} disables using native window decorations.
* <p>
* Setting this to {@code false} disables using FlatLaf native window decorations.
* This system property has higher priority than client property
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
* UI default {@code TitlePane.useWindowDecorations}.
* <p>
* (requires Window 10)
* <p>
@@ -77,26 +95,32 @@ public interface FlatSystemProperties
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
* (based on OpenJDK).
* <p>
* Setting this to {@code true} forces using JetBrains Runtime custom window decorations
* even if they are not enabled by the application.
* <p>
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
* Then FlatLaf native window decorations are used.
* <p>
* (requires Window 10)
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> true
*/
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
/**
* Specifies whether the menu bar is embedded into the window title pane
* if window decorations are enabled.
* <p>
* Setting this to {@code true} forces embedding.<br>
* Setting this to {@code false} disables embedding.
* <p>
* This system property has higher priority than client property
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
* UI default {@code TitlePane.menuBarEmbedded}.
* <p>
* (requires Window 10)
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> none
*/
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
/**
* Specifies whether menubar is embedded into custom window decorations.
* <p>
* (requires Window 10)
* <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> {@code true}
*/
String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded";
/**

View File

@@ -28,6 +28,7 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.ref.WeakReference;
import javax.swing.AbstractButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
@@ -137,10 +138,17 @@ class MnemonicHandler
// get menu bar and first menu
Component c = e.getComponent();
JRootPane rootPane = SwingUtilities.getRootPane( c );
Window window = (rootPane != null) ? SwingUtilities.getWindowAncestor( rootPane ) : null;
JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null;
if( menuBar == null && window instanceof JFrame )
menuBar = ((JFrame)window).getJMenuBar();
if( menuBar == null ) {
// get menu bar from frame/dialog because there
// may be multiple nested root panes in a frame/dialog
// (e.g. each internal frame has its own root pane)
Window window = SwingUtilities.getWindowAncestor( c );
if( window instanceof JFrame )
menuBar = ((JFrame)window).getJMenuBar();
else if( window instanceof JDialog )
menuBar = ((JDialog)window).getJMenuBar();
}
JMenu firstMenu = (menuBar != null) ? menuBar.getMenu( 0 ) : null;
// select first menu and show mnemonics

View File

@@ -0,0 +1,28 @@
/*
* 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.resources;
/**
* The only purpose of this file is to add a .class file to this package to make it non-empty.
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
*
* @author Karl Tauber
*/
interface EmptyPackage
{
}

View File

@@ -388,41 +388,35 @@ public class FlatButtonUI
}
protected Color getBackground( JComponent c ) {
boolean toolBarButton = isToolBarButton( c );
// selected state
if( ((AbstractButton)c).isSelected() ) {
// in toolbar use same colors for disabled and enabled because
// in toolbar use same background colors for disabled and enabled because
// we assume that toolbar icon is shown disabled
boolean toolBarButton = isToolBarButton( c );
return buttonStateColor( c,
toolBarButton ? toolbarSelectedBackground : selectedBackground,
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
null, null,
null,
null,
toolBarButton ? toolbarPressedBackground : pressedBackground );
}
if( !c.isEnabled() )
return disabledBackground;
// toolbar button
if( isToolBarButton( c ) ) {
ButtonModel model = ((AbstractButton)c).getModel();
if( model.isPressed() )
return toolbarPressedBackground;
if( model.isRollover() )
return toolbarHoverBackground;
// use component background if explicitly set
if( toolBarButton ) {
Color bg = c.getBackground();
if( isCustomBackground( bg ) )
return bg;
// do not paint background
return null;
return buttonStateColor( c,
isCustomBackground( bg ) ? bg : null,
null,
null,
toolbarHoverBackground,
toolbarPressedBackground );
}
boolean def = isDefaultButton( c );
return buttonStateColor( c,
getBackgroundBase( c, def ),
null,
disabledBackground,
isCustomBackground( c.getBackground() ) ? null : (def ? defaultFocusedBackground : focusedBackground),
def ? defaultHoverBackground : hoverBackground,
def ? defaultPressedBackground : pressedBackground );
@@ -444,16 +438,18 @@ public class FlatButtonUI
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
Color focusedColor, Color hoverColor, Color pressedColor )
{
AbstractButton b = (c instanceof AbstractButton) ? (AbstractButton) c : null;
if( !c.isEnabled() )
return disabledColor;
if( pressedColor != null && b != null && b.getModel().isPressed() )
return pressedColor;
if( c instanceof AbstractButton ) {
ButtonModel model = ((AbstractButton)c).getModel();
if( hoverColor != null && b != null && b.getModel().isRollover() )
return hoverColor;
if( pressedColor != null && model.isPressed() )
return pressedColor;
if( hoverColor != null && model.isRollover() )
return hoverColor;
}
if( focusedColor != null && isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c ) )
return focusedColor;

View File

@@ -243,7 +243,24 @@ public class FlatComboBoxUI
public void layoutContainer( Container parent ) {
super.layoutContainer( parent );
if ( editor != null && padding != null ) {
if( arrowButton != null ) {
Insets insets = getInsets();
int buttonWidth = parent.getPreferredSize().height - insets.top - insets.bottom;
if( buttonWidth != arrowButton.getWidth() ) {
// set width of arrow button to preferred height of combobox
int xOffset = comboBox.getComponentOrientation().isLeftToRight()
? arrowButton.getWidth() - buttonWidth
: 0;
arrowButton.setBounds( arrowButton.getX() + xOffset, arrowButton.getY(),
buttonWidth, arrowButton.getHeight() );
// update editor bounds
if( editor != null )
editor.setBounds( rectangleForCurrentValue() );
}
}
if( editor != null && padding != null ) {
// fix editor bounds by subtracting padding
editor.setBounds( FlatUIUtils.subtractInsets( editor.getBounds(), padding ) );
}

View File

@@ -16,7 +16,9 @@
package com.formdev.flatlaf.ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
@@ -52,8 +54,6 @@ import com.formdev.flatlaf.util.SystemInfo;
public class FlatMenuBarUI
extends BasicMenuBarUI
{
protected boolean unifiedBackground;
public static ComponentUI createUI( JComponent c ) {
return new FlatMenuBarUI();
}
@@ -68,8 +68,6 @@ public class FlatMenuBarUI
super.installDefaults();
LookAndFeel.installProperty( menuBar, "opaque", false );
unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
}
@Override
@@ -86,31 +84,40 @@ public class FlatMenuBarUI
@Override
public void update( Graphics g, JComponent c ) {
// do not fill background if menubar is embedded into title pane
if( isFillBackground( c ) ) {
g.setColor( c.getBackground() );
// paint background
Color background = getBackground( c );
if( background != null ) {
g.setColor( background );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
paint( g, c );
}
protected boolean isFillBackground( JComponent c ) {
// paint background in opaque or having custom background color
if( c.isOpaque() || !(c.getBackground() instanceof UIResource) )
return true;
protected Color getBackground( JComponent c ) {
Color background = c.getBackground();
// do not paint background for unified title pane
if( unifiedBackground )
return false;
// paint background if opaque or if having custom background color
if( c.isOpaque() || !(background instanceof UIResource) )
return background;
// paint background if menu bar is not the "main" menu bar
JRootPane rootPane = SwingUtilities.getRootPane( c );
if( rootPane == null || !(rootPane.getParent() instanceof Window) || rootPane.getJMenuBar() != c )
return background;
// use parent background for unified title pane
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
if( UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ) )
background = FlatUIUtils.getParentBackground( c );
// paint background in full screen mode
JRootPane rootPane = SwingUtilities.getRootPane( c );
if( rootPane == null || FlatUIUtils.isFullScreen( rootPane ) )
return true;
if( FlatUIUtils.isFullScreen( rootPane ) )
return background;
// do not paint background if menu bar is embedded into title pane
return rootPane.getJMenuBar() != c || !FlatRootPaneUI.isMenuBarEmbedded( rootPane );
return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background;
}
//---- class TakeFocus ----------------------------------------------------

View File

@@ -27,6 +27,7 @@ import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ChangeListener;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder;
@@ -40,9 +41,22 @@ import com.formdev.flatlaf.util.SystemInfo;
*/
public class FlatNativeWindowBorder
{
// can use window decorations if:
// - on Windows 10
// - not when running in JetBrains Projector, Webswing or WinPE
// - not disabled via system property
private static final boolean canUseWindowDecorations =
SystemInfo.isWindows_10_orLater &&
!SystemInfo.isProjector &&
!SystemInfo.isWebswing &&
!SystemInfo.isWinPE &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_WINDOW_DECORATIONS, true );
// check this field before using class JBRCustomDecorations to avoid unnecessary loading of that class
private static final boolean canUseJBRCustomDecorations
= SystemInfo.isJetBrainsJVM_11_orLater && SystemInfo.isWindows_10_orLater;
private static final boolean canUseJBRCustomDecorations =
canUseWindowDecorations &&
SystemInfo.isJetBrainsJVM_11_orLater &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true );
private static Boolean supported;
private static Provider nativeProvider;
@@ -62,25 +76,25 @@ public class FlatNativeWindowBorder
if( !isSupported() )
return null;
// Check whether root pane already has a window, which is the case when switching LaF.
// Check whether root pane already has a window, which is the case when
// switching from another LaF to FlatLaf.
// Also check whether the window is displayable, which is required to install
// FlatLaf native window border.
// If the window is not displayable, then it was probably closed/disposed but not yet removed
// from the list of windows that AWT maintains and returns with Window.getWindows().
// It could be also be a window that is currently hidden, but may be shown later.
Window window = SwingUtilities.windowForComponent( rootPane );
if( window != null && window.isDisplayable() ) {
install( window, FlatSystemProperties.USE_WINDOW_DECORATIONS );
return null;
}
if( window != null && window.isDisplayable() )
install( window );
// Install FlatLaf native window border, which must be done late,
// when the native window is already created, because it needs access to the window.
// Uninstall FlatLaf native window border when window is disposed (or root pane removed).
// "ancestor" property change event is fired from JComponent.addNotify() and removeNotify().
PropertyChangeListener ancestorListener = e -> {
Object newValue = e.getNewValue();
if( newValue instanceof Window )
install( (Window) newValue, FlatSystemProperties.USE_WINDOW_DECORATIONS );
install( (Window) newValue );
else if( newValue == null && e.getOldValue() instanceof Window )
uninstall( (Window) e.getOldValue() );
};
@@ -88,7 +102,7 @@ public class FlatNativeWindowBorder
return ancestorListener;
}
static void install( Window window, String systemPropertyKey ) {
static void install( Window window ) {
if( hasCustomDecoration( window ) )
return;
@@ -98,13 +112,11 @@ public class FlatNativeWindowBorder
if( window instanceof JFrame ) {
JFrame frame = (JFrame) window;
JRootPane rootPane = frame.getRootPane();
// do not enable native window border if JFrame should use system window decorations
// and if not forced to use FlatLaf/JBR native window decorations
if( !JFrame.isDefaultLookAndFeelDecorated() &&
!UIManager.getBoolean( "TitlePane.useWindowDecorations" ) &&
!FlatSystemProperties.getBoolean( systemPropertyKey, false ) )
return;
// check whether disabled via system property, client property or UI default
if( !useWindowDecorations( rootPane ) )
return;
// do not enable native window border if frame is undecorated
if( frame.isUndecorated() )
@@ -114,17 +126,15 @@ public class FlatNativeWindowBorder
setHasCustomDecoration( frame, true );
// enable Swing window decoration
frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME );
rootPane.setWindowDecorationStyle( JRootPane.FRAME );
} else if( window instanceof JDialog ) {
JDialog dialog = (JDialog) window;
JRootPane rootPane = dialog.getRootPane();
// do not enable native window border if JDialog should use system window decorations
// and if not forced to use FlatLaf/JBR native window decorations
if( !JDialog.isDefaultLookAndFeelDecorated() &&
!UIManager.getBoolean( "TitlePane.useWindowDecorations" ) &&
!FlatSystemProperties.getBoolean( systemPropertyKey, false ) )
return;
// check whether disabled via system property, client property or UI default
if( !useWindowDecorations( rootPane ) )
return;
// do not enable native window border if dialog is undecorated
if( dialog.isUndecorated() )
@@ -134,7 +144,7 @@ public class FlatNativeWindowBorder
setHasCustomDecoration( dialog, true );
// enable Swing window decoration
dialog.getRootPane().setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
rootPane.setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
}
}
@@ -144,11 +154,18 @@ public class FlatNativeWindowBorder
return;
}
if( !isSupported() )
return;
// remove listener
if( data instanceof PropertyChangeListener )
rootPane.removePropertyChangeListener( "ancestor", (PropertyChangeListener) data );
// uninstall native window border, except when switching to another FlatLaf theme
// do not uninstall when switching to another FlatLaf theme and if still enabled
if( UIManager.getLookAndFeel() instanceof FlatLaf && useWindowDecorations( rootPane ) )
return;
// uninstall native window border
Window window = SwingUtilities.windowForComponent( rootPane );
if( window != null )
uninstall( window );
@@ -158,10 +175,6 @@ public class FlatNativeWindowBorder
if( !hasCustomDecoration( window ) )
return;
// do not uninstall when switching to another FlatLaf theme
if( UIManager.getLookAndFeel() instanceof FlatLaf )
return;
// disable native window border for window
setHasCustomDecoration( window, false );
@@ -179,6 +192,14 @@ public class FlatNativeWindowBorder
}
}
private static boolean useWindowDecorations( JRootPane rootPane ) {
return FlatUIUtils.getBoolean( rootPane,
FlatSystemProperties.USE_WINDOW_DECORATIONS,
FlatClientProperties.USE_WINDOW_DECORATIONS,
"TitlePane.useWindowDecorations",
false );
}
public static boolean hasCustomDecoration( Window window ) {
if( canUseJBRCustomDecorations )
return JBRCustomDecorations.hasCustomDecoration( window );
@@ -217,37 +238,44 @@ public class FlatNativeWindowBorder
nativeProvider.setTitleBarAppIconBounds( window, appIconBounds );
}
static boolean showWindow( Window window, int cmd ) {
if( canUseJBRCustomDecorations || !isSupported() )
return false;
return nativeProvider.showWindow( window, cmd );
}
private static void initialize() {
if( supported != null )
return;
supported = false;
// requires Windows 10
if( !SystemInfo.isWindows_10_orLater )
return;
// do not use when running in JetBrains Projector
if( SystemInfo.isProjector )
return;
// check whether disabled via system property
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_WINDOW_DECORATIONS, true ) )
if( !canUseWindowDecorations )
return;
try {
/*
Class<?> cls = Class.forName( "com.formdev.flatlaf.natives.jna.windows.FlatWindowsNativeWindowBorder" );
Method m = cls.getMethod( "getInstance" );
nativeProvider = (Provider) m.invoke( null );
setNativeProvider( (Provider) m.invoke( null ) );
*/
nativeProvider = FlatWindowsNativeWindowBorder.getInstance();
supported = (nativeProvider != null);
setNativeProvider( FlatWindowsNativeWindowBorder.getInstance() );
} catch( Exception ex ) {
// ignore
}
}
/**
* @since 1.1.1
*/
public static void setNativeProvider( Provider provider ) {
if( nativeProvider != null )
throw new IllegalStateException();
nativeProvider = provider;
supported = (nativeProvider != null);
}
//---- interface Provider -------------------------------------------------
public interface Provider
@@ -258,6 +286,13 @@ public class FlatNativeWindowBorder
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds );
// commands for showWindow(); values must match Win32 API
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
int SW_MAXIMIZE = 3;
int SW_MINIMIZE = 6;
int SW_RESTORE = 9;
boolean showWindow( Window window, int cmd );
boolean isColorizationColorAffectsBorders();
Color getColorizationColor();
int getColorizationColorBalance();

View File

@@ -70,7 +70,7 @@ public class FlatPopupFactory
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector )
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), contents );
// macOS and Linux adds drop shadow to heavy weight popups

View File

@@ -95,7 +95,7 @@ public class FlatRootPaneUI
else
installBorder();
nativeWindowBorderData = FlatNativeWindowBorder.install( rootPane );
installNativeWindowBorder();
}
protected void installBorder() {
@@ -110,8 +110,7 @@ public class FlatRootPaneUI
public void uninstallUI( JComponent c ) {
super.uninstallUI( c );
FlatNativeWindowBorder.uninstall( rootPane, nativeWindowBorderData );
uninstallNativeWindowBorder();
uninstallClientDecorations();
rootPane = null;
}
@@ -137,6 +136,34 @@ public class FlatRootPaneUI
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
}
/**
* @since 1.1.2
*/
protected void installNativeWindowBorder() {
nativeWindowBorderData = FlatNativeWindowBorder.install( rootPane );
}
/**
* @since 1.1.2
*/
protected void uninstallNativeWindowBorder() {
FlatNativeWindowBorder.uninstall( rootPane, nativeWindowBorderData );
nativeWindowBorderData = null;
}
/**
* @since 1.1.2
*/
public static void updateNativeWindowBorder( JRootPane rootPane ) {
RootPaneUI rui = rootPane.getUI();
if( !(rui instanceof FlatRootPaneUI) )
return;
FlatRootPaneUI ui = (FlatRootPaneUI) rui;
ui.uninstallNativeWindowBorder();
ui.installNativeWindowBorder();
}
protected void installClientDecorations() {
boolean isNativeWindowBorderSupported = FlatNativeWindowBorder.isSupported();
@@ -218,6 +245,10 @@ public class FlatRootPaneUI
installBorder();
break;
case FlatClientProperties.USE_WINDOW_DECORATIONS:
updateNativeWindowBorder( rootPane );
break;
case FlatClientProperties.MENU_BAR_EMBEDDED:
if( titlePane != null ) {
titlePane.menuBarChanged();
@@ -225,6 +256,12 @@ public class FlatRootPaneUI
rootPane.repaint();
}
break;
case FlatClientProperties.TITLE_BAR_BACKGROUND:
case FlatClientProperties.TITLE_BAR_FOREGROUND:
if( titlePane != null )
titlePane.titleBarColorsChanged();
break;
}
}
@@ -431,7 +468,9 @@ public class FlatRootPaneUI
(parent instanceof JFrame &&
(((JFrame)parent).getJMenuBar() == null ||
!((JFrame)parent).getJMenuBar().isVisible())) ||
parent instanceof JDialog;
(parent instanceof JDialog &&
(((JDialog)parent).getJMenuBar() == null ||
!((JDialog)parent).getJMenuBar().isVisible()));
}
}
}

View File

@@ -375,8 +375,8 @@ public class FlatSpinnerUI
Rectangle editorRect = new Rectangle( r );
Rectangle buttonsRect = new Rectangle( r );
// make button area square
int buttonsWidth = r.height;
// make button area square (if spinner has preferred height)
int buttonsWidth = parent.getPreferredSize().height - insets.top - insets.bottom;
buttonsRect.width = buttonsWidth;
if( parent.getComponentOrientation().isLeftToRight() ) {

View File

@@ -46,10 +46,13 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault SplitPaneDivider.border Border
* @uiDefault SplitPaneDivider.draggingColor Color only used if continuousLayout is false
*
* <!-- JSplitPane -->
*
* @uiDefault SplitPane.continuousLayout boolean
*
* <!-- FlatSplitPaneUI -->
*
* @uiDefault Component.arrowType String chevron (default) or triangle
* @uiDefault SplitPane.continuousLayout boolean
* @uiDefault SplitPaneDivider.oneTouchArrowColor Color
* @uiDefault SplitPaneDivider.oneTouchHoverArrowColor Color
* @uiDefault SplitPaneDivider.oneTouchPressedArrowColor Color
@@ -65,7 +68,6 @@ public class FlatSplitPaneUI
extends BasicSplitPaneUI
{
protected String arrowType;
private Boolean continuousLayout;
protected Color oneTouchArrowColor;
protected Color oneTouchHoverArrowColor;
protected Color oneTouchPressedArrowColor;
@@ -85,8 +87,6 @@ public class FlatSplitPaneUI
oneTouchPressedArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchPressedArrowColor" );
super.installDefaults();
continuousLayout = (Boolean) UIManager.get( "SplitPane.continuousLayout" );
}
@Override
@@ -98,11 +98,6 @@ public class FlatSplitPaneUI
oneTouchPressedArrowColor = null;
}
@Override
public boolean isContinuousLayout() {
return super.isContinuousLayout() || (continuousLayout != null && Boolean.TRUE.equals( continuousLayout ));
}
@Override
public BasicSplitPaneDivider createDefaultDivider() {
return new FlatSplitPaneDivider( this );

View File

@@ -722,6 +722,13 @@ public class FlatTabbedPaneUI
}
protected Insets getRealTabAreaInsets( int tabPlacement ) {
// this is to avoid potential NPE in ensureSelectedTabIsVisible()
// (see https://github.com/JFormDesigner/FlatLaf/issues/299)
// but now should actually never occur because added more checks to
// ensureSelectedTabIsVisibleLater() and ensureSelectedTabIsVisible()
if( tabAreaInsets == null )
tabAreaInsets = new Insets( 0, 0, 0, 0 );
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
Insets insets = (Insets) currentTabAreaInsets.clone();
@@ -1386,13 +1393,18 @@ public class FlatTabbedPaneUI
}
protected void ensureSelectedTabIsVisibleLater() {
// do nothing if not yet displayable or if not invoked from dispatch thread,
// which may be the case when creating/modifying in another thread
if( !tabPane.isDisplayable() || !EventQueue.isDispatchThread() )
return;
EventQueue.invokeLater( () -> {
ensureSelectedTabIsVisible();
} );
}
protected void ensureSelectedTabIsVisible() {
if( tabPane == null || tabViewport == null )
if( tabPane == null || tabViewport == null || !tabPane.isDisplayable() )
return;
ensureCurrentLayout();

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
@@ -87,6 +88,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TitlePane.centerTitle boolean
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
* @uiDefault TitlePane.menuBarTitleGap int
* @uiDefault TitlePane.icon Icon
* @uiDefault TitlePane.closeIcon Icon
* @uiDefault TitlePane.iconifyIcon Icon
* @uiDefault TitlePane.maximizeIcon Icon
@@ -104,7 +106,6 @@ public class FlatTitlePane
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
protected final boolean unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
@@ -197,14 +198,16 @@ public class FlatTitlePane
}
// If menu bar is embedded and contains a horizontal glue component,
// then move the title label to the same location as the glue component.
// then move the title label to the same location as the glue component
// and give it the same width.
// This allows placing any component on the trailing side of the title pane.
JMenuBar menuBar = rootPane.getJMenuBar();
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
Component horizontalGlue = findHorizontalGlue( menuBar );
if( horizontalGlue != null ) {
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, titleLabel );
titleLabel.setLocation( titleLabel.getX() + glueLocation.x, titleLabel.getY() );
titleLabel.setBounds( titleLabel.getX() + glueLocation.x, titleLabel.getY(),
horizontalGlue.getWidth(), titleLabel.getHeight() );
}
}
}
@@ -263,10 +266,17 @@ public class FlatTitlePane
}
protected void activeChanged( boolean active ) {
boolean hasEmbeddedMenuBar = hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() );
Color background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground );
Color foreground = FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground );
Color titleForeground = (hasEmbeddedMenuBar && active) ? FlatUIUtils.nonUIResource( embeddedForeground ) : foreground;
Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null );
Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null );
Color titleForeground = foreground;
if( background == null )
background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground );
if( foreground == null ) {
foreground = FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground );
titleForeground = (active && hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ))
? FlatUIUtils.nonUIResource( embeddedForeground )
: foreground;
}
setBackground( background );
titleLabel.setForeground( titleForeground );
@@ -344,7 +354,7 @@ public class FlatTitlePane
iconLabel.setIcon( FlatTitlePaneIcon.create( images, iconSize ) );
else {
// no icon set on window --> use default icon
Icon defaultIcon = UIManager.getIcon( "InternalFrame.icon" );
Icon defaultIcon = UIManager.getIcon( "TitlePane.icon" );
if( defaultIcon != null && (defaultIcon.getIconWidth() == 0 || defaultIcon.getIconHeight() == 0) )
defaultIcon = null;
if( defaultIcon != null ) {
@@ -427,9 +437,11 @@ public class FlatTitlePane
*/
protected boolean isMenuBarEmbedded() {
// not storing value of "TitlePane.menuBarEmbedded" in class to allow changing at runtime
return UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) &&
FlatClientProperties.clientPropertyBoolean( rootPane, FlatClientProperties.MENU_BAR_EMBEDDED, true ) &&
FlatSystemProperties.getBoolean( FlatSystemProperties.MENUBAR_EMBEDDED, true );
return FlatUIUtils.getBoolean( rootPane,
FlatSystemProperties.MENUBAR_EMBEDDED,
FlatClientProperties.MENU_BAR_EMBEDDED,
"TitlePane.menuBarEmbedded",
false );
}
protected Rectangle getMenuBarBounds() {
@@ -450,9 +462,13 @@ public class FlatTitlePane
// This allows placing any component on the trailing side of the title pane.
Component horizontalGlue = findHorizontalGlue( rootPane.getJMenuBar() );
if( horizontalGlue != null ) {
int titleWidth = Math.max( titleLabel.getWidth(), 0 ); // title width may be negative
boolean leftToRight = getComponentOrientation().isLeftToRight();
int titleWidth = leftToRight
? buttonPanel.getX() - (leftPanel.getX() + leftPanel.getWidth())
: leftPanel.getX() - (buttonPanel.getX() + buttonPanel.getWidth());
titleWidth = Math.max( titleWidth, 0 ); // title width may be negative
bounds.width += titleWidth;
if( !getComponentOrientation().isLeftToRight() )
if( !leftToRight )
bounds.x -= titleWidth;
}
@@ -460,6 +476,9 @@ public class FlatTitlePane
}
protected Component findHorizontalGlue( JMenuBar menuBar ) {
if( menuBar == null )
return null;
int count = menuBar.getComponentCount();
for( int i = count - 1; i >= 0; i-- ) {
Component c = menuBar.getComponent( i );
@@ -469,6 +488,11 @@ public class FlatTitlePane
return null;
}
protected void titleBarColorsChanged() {
activeChanged( window == null || window.isActive() );
repaint();
}
protected void menuBarChanged() {
menuBarPlaceholder.invalidate();
@@ -513,10 +537,12 @@ debug*/
@Override
protected void paintComponent( Graphics g ) {
if( !unifiedBackground ) {
g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
}
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
g.setColor( (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
? FlatUIUtils.getParentBackground( this )
: getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
}
protected void repaintWindowBorder() {
@@ -533,10 +559,12 @@ debug*/
* Iconifies the window.
*/
protected void iconify() {
if( window instanceof Frame ) {
Frame frame = (Frame) window;
if( !(window instanceof Frame) )
return;
Frame frame = (Frame) window;
if( !FlatNativeWindowBorder.showWindow( window, FlatNativeWindowBorder.Provider.SW_MINIMIZE ) )
frame.setExtendedState( frame.getExtendedState() | Frame.ICONIFIED );
}
}
/**
@@ -554,7 +582,8 @@ debug*/
rootPane.putClientProperty( "_flatlaf.maximizedBoundsUpToDate", true );
// maximize window
frame.setExtendedState( frame.getExtendedState() | Frame.MAXIMIZED_BOTH );
if( !FlatNativeWindowBorder.showWindow( frame, FlatNativeWindowBorder.Provider.SW_MAXIMIZE ) )
frame.setExtendedState( frame.getExtendedState() | Frame.MAXIMIZED_BOTH );
}
protected void updateMaximizedBounds() {
@@ -642,8 +671,11 @@ debug*/
* Restores the window size.
*/
protected void restore() {
if( window instanceof Frame ) {
Frame frame = (Frame) window;
if( !(window instanceof Frame) )
return;
Frame frame = (Frame) window;
if( !FlatNativeWindowBorder.showWindow( window, FlatNativeWindowBorder.Provider.SW_RESTORE ) ) {
int state = frame.getExtendedState();
frame.setExtendedState( ((state & Frame.ICONIFIED) != 0)
? (state & ~Frame.ICONIFIED)
@@ -710,31 +742,34 @@ debug*/
if( r != null )
hitTestSpots.add( r );
r = getNativeHitTestSpot( menuBarPlaceholder );
if( r != null ) {
Component horizontalGlue = findHorizontalGlue( rootPane.getJMenuBar() );
if( horizontalGlue != null ) {
// If menu bar is embedded and contains a horizontal glue component,
// then split the hit test spot into two spots so that
// the glue component area can used to move the window.
JMenuBar menuBar = rootPane.getJMenuBar();
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
r = getNativeHitTestSpot( menuBarPlaceholder );
if( r != null ) {
Component horizontalGlue = findHorizontalGlue( menuBar );
if( horizontalGlue != null ) {
// If menu bar is embedded and contains a horizontal glue component,
// then split the hit test spot into two spots so that
// the glue component area can used to move the window.
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
Rectangle r2;
if( getComponentOrientation().isLeftToRight() ) {
int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x;
r.width -= trailingWidth;
r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height );
} else {
int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW);
r.x += leadingWidth;
r.width -= leadingWidth;
r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height );
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
Rectangle r2;
if( getComponentOrientation().isLeftToRight() ) {
int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x;
r.width -= trailingWidth;
r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height );
} else {
int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW);
r.x += leadingWidth;
r.width -= leadingWidth;
r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height );
}
r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
hitTestSpots.add( r2 );
}
r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
hitTestSpots.add( r2 );
}
hitTestSpots.add( r );
hitTestSpots.add( r );
}
}
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds );
@@ -784,7 +819,7 @@ debug*/
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) )
insets.bottom += UIScale.scale( 1 );
if( hasNativeCustomDecoration() )
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
insets = FlatUIUtils.addInsets( insets, WindowTopBorder.getInstance().getBorderInsets() );
return insets;
@@ -803,7 +838,7 @@ debug*/
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
}
if( hasNativeCustomDecoration() )
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
WindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
}
@@ -811,6 +846,12 @@ debug*/
JMenuBar menuBar = rootPane.getJMenuBar();
return hasVisibleEmbeddedMenuBar( menuBar ) ? menuBar.getBorder() : null;
}
protected boolean isWindowMaximized( Component c ) {
return window instanceof Frame
? (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
: false;
}
}
//---- class FlatTitleLabelUI ---------------------------------------------

View File

@@ -54,6 +54,7 @@ import javax.swing.border.CompoundBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils;
@@ -140,6 +141,25 @@ public class FlatUIUtils
return (value instanceof Number) ? ((Number)value).floatValue() : defaultValue;
}
/**
* @since 1.1.2
*/
public static boolean getBoolean( JComponent c, String systemPropertyKey,
String clientPropertyKey, String uiKey, boolean defaultValue )
{
// check whether forced to true/false via system property
Boolean value = FlatSystemProperties.getBooleanStrict( systemPropertyKey, null );
if( value != null )
return value;
// check whether forced to true/false via client property
value = FlatClientProperties.clientPropertyBooleanStrict( c, clientPropertyKey, null );
if( value != null )
return value;
return getUIBoolean( uiKey, defaultValue );
}
public static boolean isChevron( String arrowType ) {
return !"triangle".equals( arrowType );
}
@@ -185,7 +205,8 @@ public class FlatUIUtils
/**
* Returns whether the given component is the permanent focus owner and
* is in the active window. Used to paint focus indicators.
* is in the active window or in a popup window owned by the active window.
* Used to paint focus indicators.
*/
@SuppressWarnings( "unchecked" )
public static boolean isPermanentFocusOwner( Component c ) {
@@ -195,12 +216,18 @@ public class FlatUIUtils
Object value = ((JComponent)c).getClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER );
if( value instanceof Predicate ) {
return ((Predicate<JComponent>)value).test( (JComponent) c ) &&
keyboardFocusManager.getActiveWindow() == SwingUtilities.windowForComponent( c );
isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
}
}
return keyboardFocusManager.getPermanentFocusOwner() == c &&
keyboardFocusManager.getActiveWindow() == SwingUtilities.windowForComponent( c );
isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
}
private static boolean isInActiveWindow( Component c, Window activeWindow ) {
Window window = SwingUtilities.windowForComponent( c );
return window == activeWindow ||
(window != null && window.getType() == Window.Type.POPUP && window.getOwner() == activeWindow);
}
/**

View File

@@ -103,8 +103,7 @@ class FlatWindowsNativeWindowBorder
if( SystemInfo.isX86_64 )
libraryName += "_64";
nativeLibrary = new NativeLibrary( libraryName,
FlatWindowsNativeWindowBorder.class.getClassLoader(), true );
nativeLibrary = new NativeLibrary( libraryName, null, true );
}
// check whether native library was successfully loaded
@@ -197,6 +196,16 @@ class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
}
@Override
public boolean showWindow( Window window, int cmd ) {
WndProc wndProc = windowsMap.get( window );
if( wndProc == null )
return false;
wndProc.showWindow( wndProc.hwnd, cmd );
return true;
}
@Override
public boolean isColorizationColorAffectsBorders() {
updateColorization();
@@ -299,6 +308,18 @@ class FlatWindowsNativeWindowBorder
this.window = window;
hwnd = installImpl( window );
// remove the OS window title bar
if( window instanceof JFrame && ((JFrame)window).getExtendedState() != 0 ) {
// In case that the frame should be maximized or minimized immediately
// when showing, then it is necessary to defer ::SetWindowPos() invocation.
// Otherwise the frame will not be maximized or minimized.
// This occurs only if frame.pack() was no invoked.
EventQueue.invokeLater( () -> {
updateFrame( hwnd );
});
} else
updateFrame( hwnd );
}
void uninstall() {
@@ -310,6 +331,8 @@ class FlatWindowsNativeWindowBorder
private native long installImpl( Window window );
private native void uninstallImpl( long hwnd );
private native void updateFrame( long hwnd );
private native void showWindow( long hwnd, int cmd );
// invoked from native code
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) {

View File

@@ -36,7 +36,6 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.BorderUIResource;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.SystemInfo;
@@ -73,7 +72,7 @@ public class JBRCustomDecorations
// check whether root pane already has a parent, which is the case when switching LaF
Window window = SwingUtilities.windowForComponent( rootPane );
if( window != null ) {
FlatNativeWindowBorder.install( window, FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS );
FlatNativeWindowBorder.install( window );
return null;
}
@@ -89,7 +88,7 @@ public class JBRCustomDecorations
Container parent = e.getChangedParent();
if( parent instanceof Window )
FlatNativeWindowBorder.install( (Window) parent, FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS );
FlatNativeWindowBorder.install( (Window) parent );
// remove listener since it is actually not possible to uninstall JBR decorations
// use invokeLater to remove listener to avoid that listener
@@ -165,10 +164,6 @@ public class JBRCustomDecorations
if( !SystemInfo.isJetBrainsJVM_11_orLater || !SystemInfo.isWindows_10_orLater )
return;
// check whether disabled via system property
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true ) )
return;
try {
Class<?> awtAcessorClass = Class.forName( "sun.awt.AWTAccessor" );
Class<?> compAccessorClass = Class.forName( "sun.awt.AWTAccessor$ComponentAccessor" );

View File

@@ -42,9 +42,15 @@ public class NativeLibrary
/**
* Load native library from given classloader.
* <p>
* Note regarding Java Platform Module System (JPMS):
* If classloader is {@code null}, the library can be only loaded from the module
* that contains this class.
* If classloader is not {@code null}, then the package that contains the library
* must be specified as "open" in module-info.java of the module that contains the library.
*
* @param libraryName resource name of the native library (without "lib" prefix and without extension)
* @param classLoader the classloader used to locate the library
* @param classLoader the classloader used to locate the library, or {@code null}
* @param supported whether the native library is supported on the current platform
*/
public NativeLibrary( String libraryName, ClassLoader classLoader, boolean supported ) {
@@ -68,7 +74,9 @@ public class NativeLibrary
libraryName = decorateLibraryName( libraryName );
// find library
URL libraryUrl = classLoader.getResource( libraryName );
URL libraryUrl = (classLoader != null)
? classLoader.getResource( libraryName )
: NativeLibrary.class.getResource( "/" + libraryName );
if( libraryUrl == null ) {
log( "Library '" + libraryName + "' not found", null );
return false;

View File

@@ -56,6 +56,8 @@ public class SystemInfo
// other
/** @since 1.1 */ public static final boolean isProjector;
/** @since 1.1.2 */ public static final boolean isWebswing;
/** @since 1.1.1 */ public static final boolean isWinPE;
static {
// platforms
@@ -91,6 +93,8 @@ public class SystemInfo
// other
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
isWebswing = (System.getProperty( "webswing.rootDir" ) != null);
isWinPE = isWindows && "X:\\Windows\\System32".equalsIgnoreCase( System.getProperty( "user.dir" ) );
}
public static long scanVersion( String version ) {

View File

@@ -180,7 +180,7 @@ public class UIScale
// apply custom scale factor specified in system property "flatlaf.uiScale"
float customScaleFactor = getCustomScaleFactor();
if( customScaleFactor > 0 ) {
setUserScaleFactor( customScaleFactor );
setUserScaleFactor( customScaleFactor, false );
return;
}
@@ -230,7 +230,7 @@ public class UIScale
} else
newScaleFactor = computeScaleFactor( font );
setUserScaleFactor( newScaleFactor );
setUserScaleFactor( newScaleFactor, true );
}
private static float computeScaleFactor( Font font ) {
@@ -274,7 +274,7 @@ public class UIScale
if( scaleFactor == fontScaleFactor )
return font;
int newFontSize = Math.round( (font.getSize() / fontScaleFactor) * scaleFactor );
int newFontSize = Math.max( Math.round( (font.getSize() / fontScaleFactor) * scaleFactor ), 1 );
return new FontUIResource( font.deriveFont( (float) newFontSize ) );
}
@@ -322,11 +322,18 @@ public class UIScale
/**
* Sets the user scale factor.
*/
private static void setUserScaleFactor( float scaleFactor ) {
if( scaleFactor <= 1f )
scaleFactor = 1f;
else // round scale factor to 1/4
scaleFactor = Math.round( scaleFactor * 4f ) / 4f;
private static void setUserScaleFactor( float scaleFactor, boolean normalize ) {
if( normalize ) {
if( scaleFactor < 1f ) {
scaleFactor = FlatSystemProperties.getBoolean( FlatSystemProperties.UI_SCALE_ALLOW_SCALE_DOWN, false )
? Math.round( scaleFactor * 10f ) / 10f // round small scale factor to 1/10
: 1f;
} else if( scaleFactor > 1f ) // round scale factor to 1/4
scaleFactor = Math.round( scaleFactor * 4f ) / 4f;
}
// minimum scale factor
scaleFactor = Math.max( scaleFactor, 0.1f );
float oldScaleFactor = UIScale.scaleFactor;
UIScale.scaleFactor = scaleFactor;

View File

@@ -22,6 +22,28 @@
# - https://www.formdev.com/flatlaf/how-to-customize/
#
#---- system colors ----
# fix (most) system colors because they are usually not set in .json files
desktop = lazy(TextField.background)
activeCaptionText = lazy(TextField.foreground)
inactiveCaptionText = lazy(TextField.foreground)
window = lazy(Panel.background)
windowBorder = lazy(TextField.foreground)
windowText = lazy(TextField.foreground)
menu = lazy(Menu.background)
menuText = lazy(Menu.foreground)
text = lazy(TextField.background)
textText = lazy(TextField.foreground)
textHighlight = lazy(TextField.selectionBackground)
textHighlightText = lazy(TextField.selectionForeground)
textInactiveText = lazy(TextField.inactiveForeground)
control = lazy(Panel.background)
controlText = lazy(TextField.foreground)
info = lazy(ToolTip.background)
infoText = lazy(ToolTip.foreground)
#---- Button ----
Button.startBackground = $Button.background

View File

@@ -24,7 +24,6 @@ import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.StyleContext;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.demo.HintManager.Hint;
import com.formdev.flatlaf.demo.extras.*;
@@ -35,8 +34,8 @@ import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.extras.components.FlatButton;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
import com.formdev.flatlaf.extras.FlatSVGUtils;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
import com.formdev.flatlaf.ui.JBRCustomDecorations;
import com.formdev.flatlaf.util.SystemInfo;
import net.miginfocom.layout.ConstraintParser;
import net.miginfocom.layout.LC;
import net.miginfocom.layout.UnitValue;
@@ -144,35 +143,21 @@ class DemoFrame
private void windowDecorationsChanged() {
boolean windowDecorations = windowDecorationsCheckBoxMenuItem.isSelected();
// change window decoration of demo main frame
if( FlatNativeWindowBorder.isSupported() ) {
FlatNativeWindowBorder.setHasCustomDecoration( this, windowDecorations );
getRootPane().setWindowDecorationStyle( windowDecorations ? JRootPane.FRAME : JRootPane.NONE );
} else {
dispose();
setUndecorated( windowDecorations );
getRootPane().setWindowDecorationStyle( windowDecorations ? JRootPane.FRAME : JRootPane.NONE );
setVisible( true );
}
menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations );
// change window decoration of all frames and dialogs
FlatLaf.setUseNativeWindowDecorations( windowDecorations );
// enable/disable window decoration for later created frames/dialogs
UIManager.put( "TitlePane.useWindowDecorations", windowDecorations );
menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations );
unifiedTitleBarMenuItem.setEnabled( windowDecorations );
}
private void menuBarEmbeddedChanged() {
getRootPane().putClientProperty( FlatClientProperties.MENU_BAR_EMBEDDED,
menuBarEmbeddedCheckBoxMenuItem.isSelected() ? null : false );
// alternative method for all frames and menu bars in an application
// UIManager.put( "TitlePane.menuBarEmbedded", menuBarEmbeddedCheckBoxMenuItem.isSelected() );
// revalidate();
// repaint();
UIManager.put( "TitlePane.menuBarEmbedded", menuBarEmbeddedCheckBoxMenuItem.isSelected() );
FlatLaf.revalidateAndRepaintAllFramesAndDialogs();
}
private void unifiedTitleBar() {
UIManager.put( "TitlePane.unifiedBackground", unifiedTitleBarMenuItem.isSelected() );
FlatLaf.updateUI();
FlatLaf.repaintAllFramesAndDialogs();
}
private void underlineMenuSelection() {
@@ -280,7 +265,7 @@ class DemoFrame
// add font sizes
fontMenu.addSeparator();
ArrayList<String> sizes = new ArrayList<>( Arrays.asList(
"10", "12", "14", "16", "18", "20", "24", "28" ) );
"10", "11", "12", "14", "16", "18", "20", "24", "28" ) );
if( !sizes.contains( currentSize ) )
sizes.add( currentSize );
sizes.sort( String.CASE_INSENSITIVE_ORDER );
@@ -602,7 +587,7 @@ class DemoFrame
optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem);
//---- unifiedTitleBarMenuItem ----
unifiedTitleBarMenuItem.setText("Unified Title Bar");
unifiedTitleBarMenuItem.setText("Unified window title bar");
unifiedTitleBarMenuItem.addActionListener(e -> unifiedTitleBar());
optionsMenu.add(unifiedTitleBarMenuItem);
@@ -748,10 +733,20 @@ class DemoFrame
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
boolean supportsWindowDecorations = UIManager.getLookAndFeel()
.getSupportsWindowDecorations() || FlatNativeWindowBorder.isSupported();
windowDecorationsCheckBoxMenuItem.setEnabled( supportsWindowDecorations && !JBRCustomDecorations.isSupported() );
menuBarEmbeddedCheckBoxMenuItem.setEnabled( supportsWindowDecorations );
if( FlatLaf.supportsNativeWindowDecorations() ) {
if( JBRCustomDecorations.isSupported() ) {
// If the JetBrains Runtime is used, it forces the use of it's own custom
// window decoration, which can not disabled.
windowDecorationsCheckBoxMenuItem.setEnabled( false );
}
} else {
unsupported( windowDecorationsCheckBoxMenuItem );
unsupported( menuBarEmbeddedCheckBoxMenuItem );
unsupported( unifiedTitleBarMenuItem );
}
if( SystemInfo.isMacOS )
unsupported( underlineMenuSelectionMenuItem );
// remove contentPanel bottom insets
MigLayout layout = (MigLayout) contentPanel.getLayout();
@@ -766,6 +761,12 @@ class DemoFrame
layout.setLayoutConstraints( lc );
}
private void unsupported( JCheckBoxMenuItem menuItem ) {
menuItem.setEnabled( false );
menuItem.setSelected( false );
menuItem.setToolTipText( "Not supported on your system." );
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JMenu fontMenu;
private JMenu optionsMenu;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -362,7 +362,7 @@ new FormModel {
} )
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
name: "unifiedTitleBarMenuItem"
"text": "Unified Title Bar"
"text": "Unified window title bar"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}

View File

@@ -475,7 +475,7 @@ public class FlatInspector
f.setAccessible( true );
Object ui = f.get( c );
appendRow( buf, "UI", (ui != null ? ui.getClass().getName() : "null") );
} catch( NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex ) {
} catch( Exception ex ) {
// ignore
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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.extras.resources;
/**
* The only purpose of this file is to add a .class file to this package to make it non-empty.
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
*
* @author Karl Tauber
*/
interface EmptyPackage
{
}

View File

@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.Map;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIDefaults.ActiveValue;
import com.formdev.flatlaf.FlatDefaultsAddon;
import com.formdev.flatlaf.FlatLaf;
@@ -70,6 +71,9 @@ public class FlatJideOssDefaultsAddon
* own UI defaults, we have to first remember our UI defaults in the initializer
* (invoked before JIDE overwrites UI defaults) and then restore them in the customizer.
* <p>
* Do not register this class yourself with JIDE.
* It is automatically registered.
* <p>
* Invoked from {@link LookAndFeelFactory#installJideExtension()}.
*/
public static class FlatJideUIDefaultsCustomizer
@@ -79,6 +83,10 @@ public class FlatJideOssDefaultsAddon
@Override
public void initialize( UIDefaults defaults ) {
// do nothing in other Lafs if (wrongly) registered with LookAndFeelFactory.addUIDefaultsInitializer()
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) )
return;
jideDefaults = new HashMap<>();
for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
@@ -96,6 +104,10 @@ public class FlatJideOssDefaultsAddon
@Override
public void customize( UIDefaults defaults ) {
// do nothing in other Lafs if (wrongly) registered with LookAndFeelFactory.addUIDefaultsCustomizer()
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) )
return;
if( jideDefaults != null ) {
defaults.putAll( jideDefaults );
jideDefaults = null;

View File

@@ -183,6 +183,16 @@ public class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
}
@Override
public boolean showWindow( Window window, int cmd ) {
WndProc wndProc = windowsMap.get( window );
if( wndProc == null )
return false;
User32.INSTANCE.ShowWindow( wndProc.hwnd, cmd );
return true;
}
@Override
public boolean isColorizationColorAffectsBorders() {
updateColorization();
@@ -328,7 +338,16 @@ public class FlatWindowsNativeWindowBorder
defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this );
// remove the OS window title bar
updateFrame();
if( window instanceof JFrame && ((JFrame)window).getExtendedState() != 0 ) {
// In case that the frame should be maximized or minimized immediately
// when showing, then it is necessary to defer ::SetWindowPos() invocation.
// Otherwise the frame will not be maximized or minimized.
// This occurs only if frame.pack() was no invoked.
EventQueue.invokeLater( () -> {
updateFrame();
});
} else
updateFrame();
}
void uninstall() {
@@ -348,7 +367,7 @@ public class FlatWindowsNativeWindowBorder
private void updateFrame() {
// this sends WM_NCCALCSIZE and removes/shows the window title bar
User32.INSTANCE.SetWindowPos( hwnd, hwnd, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER );
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
}
/**

View File

@@ -45,6 +45,20 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
FlatWndProc::uninstall( env, obj, reinterpret_cast<HWND>( hwnd ) );
}
extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame
( JNIEnv* env, jobject obj, jlong hwnd )
{
FlatWndProc::updateFrame( reinterpret_cast<HWND>( hwnd ) );
}
extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow
( JNIEnv* env, jobject obj, jlong hwnd, jint cmd )
{
::ShowWindow( reinterpret_cast<HWND>( hwnd ), cmd );
}
//---- class FlatWndProc fields -----------------------------------------------
int FlatWndProc::initialized = 0;
@@ -89,9 +103,6 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) );
// remove the OS window title bar
fwp->updateFrame();
return hwnd;
}
@@ -109,7 +120,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
// show the OS window title bar
fwp->updateFrame();
updateFrame( hwnd );
// cleanup
env->DeleteGlobalRef( fwp->obj );
@@ -134,10 +145,10 @@ void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) {
initialized = 1;
}
void FlatWndProc::updateFrame() {
void FlatWndProc::updateFrame( HWND hwnd ) {
// this sends WM_NCCALCSIZE and removes/shows the window title bar
::SetWindowPos( hwnd, hwnd, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER );
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
}
LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {

View File

@@ -25,6 +25,7 @@ class FlatWndProc
public:
static HWND install( JNIEnv *env, jobject obj, jobject window );
static void uninstall( JNIEnv *env, jobject obj, HWND hwnd );
static void updateFrame( HWND hwnd );
private:
static int initialized;
@@ -42,7 +43,6 @@ private:
FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj );
void updateFrame();
static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

View File

@@ -31,6 +31,22 @@ JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorde
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_uninstallImpl
(JNIEnv *, jobject, jlong);
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: updateFrame
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame
(JNIEnv *, jobject, jlong);
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: showWindow
* Signature: (JI)V
*/
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow
(JNIEnv *, jobject, jlong, jint);
#ifdef __cplusplus
}
#endif

View File

@@ -1175,6 +1175,7 @@ TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResou
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #959595 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
TitlePane.icon [lazy] 16,16 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]

View File

@@ -1180,6 +1180,7 @@ TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResou
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #595959 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #000000 javax.swing.plaf.ColorUIResource [UI]
TitlePane.icon [lazy] 16,16 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]

View File

@@ -1165,6 +1165,7 @@ TextPaneUI com.formdev.flatlaf.ui.FlatTextPaneUI
#---- TitlePane ----
TitlePane.background #00ff00 javax.swing.plaf.ColorUIResource [UI]
TitlePane.borderColor #ff0000 javax.swing.plaf.ColorUIResource [UI]
TitlePane.buttonMaximizedHeight 22
TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.centerTitle false
@@ -1175,6 +1176,7 @@ TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWin
TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResource [UI]
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #0000ff javax.swing.plaf.ColorUIResource [UI]
TitlePane.icon [lazy] 16,16 sun.swing.ImageIconUIResource [UI] (sun.awt.image.ToolkitImage)
TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]

View File

@@ -26,10 +26,18 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.WeakHashMap;
import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.FlatInspector;
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
import com.formdev.flatlaf.util.SystemInfo;
import net.miginfocom.swing.*;
/**
@@ -63,7 +71,7 @@ public class FlatNativeWindowBorderTest
frame.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
frame.pack();
frame.setSize( new Dimension( 800, 600 ) );
frame.setLocationRelativeTo( null );
int offset = 20 * Window.getWindows().length;
frame.setLocation( frame.getX() + offset, frame.getY() + offset );
@@ -80,7 +88,7 @@ public class FlatNativeWindowBorderTest
dialog.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
dialog.pack();
dialog.setSize( new Dimension( 800, 600 ) );
dialog.setLocationRelativeTo( owner );
dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 );
dialog.setVisible( true );
@@ -96,7 +104,6 @@ public class FlatNativeWindowBorderTest
hideWindowButton.setEnabled( false );
setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) );
setPreferredSize( new Dimension( 800, 600 ) );
updateInfo();
@@ -144,6 +151,26 @@ public class FlatNativeWindowBorderTest
System.out.println( windowId + " windowDeactivated" );
}
} );
window.addWindowStateListener( e -> {
System.out.println( windowId + " windowStateChanged " + e.getOldState() + " --> " + e.getNewState() );
} );
registerSwitchToLookAndFeel( "F1", FlatLightLaf.class.getName() );
registerSwitchToLookAndFeel( "F2", FlatDarkLaf.class.getName() );
registerSwitchToLookAndFeel( "F3", FlatIntelliJLaf.class.getName() );
registerSwitchToLookAndFeel( "F4", FlatDarculaLaf.class.getName() );
registerSwitchToLookAndFeel( "F8", FlatTestLaf.class.getName() );
if( SystemInfo.isWindows )
registerSwitchToLookAndFeel( "F9", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
else if( SystemInfo.isMacOS )
registerSwitchToLookAndFeel( "F9", "com.apple.laf.AquaLookAndFeel" );
else if( SystemInfo.isLinux )
registerSwitchToLookAndFeel( "F9", "com.sun.java.swing.plaf.gtk.GTKLookAndFeel" );
registerSwitchToLookAndFeel( "F12", MetalLookAndFeel.class.getName() );
registerSwitchToLookAndFeel( "F11", NimbusLookAndFeel.class.getName() );
}
private void updateInfo() {
@@ -220,6 +247,28 @@ public class FlatNativeWindowBorderTest
(r1.y + r1.height) - (r2.y + r2.height) );
}
private void registerSwitchToLookAndFeel( String keyStrokeStr, String lafClassName ) {
KeyStroke keyStroke = KeyStroke.getKeyStroke( keyStrokeStr );
if( keyStroke == null )
throw new IllegalArgumentException( "Invalid key stroke '" + keyStrokeStr + "'" );
((JComponent)((RootPaneContainer)window).getContentPane()).registerKeyboardAction(
e -> applyLookAndFeel( lafClassName ),
keyStroke,
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
}
private void applyLookAndFeel( String lafClassName ) {
EventQueue.invokeLater( () -> {
try {
UIManager.setLookAndFeel( lafClassName );
FlatLaf.updateUI();
} catch( Exception ex ) {
ex.printStackTrace();
}
} );
}
private void resizableChanged() {
if( window instanceof Frame )
((Frame)window).setResizable( resizableCheckBox.isSelected() );
@@ -255,7 +304,11 @@ public class FlatNativeWindowBorderTest
}
private void nativeChanged() {
FlatNativeWindowBorder.setHasCustomDecoration( window, nativeCheckBox.isSelected() );
FlatLaf.setUseNativeWindowDecorations( nativeCheckBox.isSelected() );
}
private void native2Changed() {
((RootPaneContainer)window).getRootPane().putClientProperty( FlatClientProperties.USE_WINDOW_DECORATIONS, native2CheckBox.getChecked() );
}
private void revalidateLayout() {
@@ -298,6 +351,23 @@ public class FlatNativeWindowBorderTest
}
}
private void reopen() {
window.dispose();
window.setVisible( true );
}
private void reshow() {
window.setVisible( false );
try {
Thread.sleep( 100 );
} catch( InterruptedException ex ) {
// ignore
}
window.setVisible( true );
}
private void close() {
window.dispose();
}
@@ -310,12 +380,15 @@ public class FlatNativeWindowBorderTest
undecoratedCheckBox = new JCheckBox();
fullScreenCheckBox = new JCheckBox();
nativeCheckBox = new JCheckBox();
revalidateButton = new JButton();
replaceRootPaneButton = new JButton();
native2CheckBox = new FlatTriStateCheckBox();
openDialogButton = new JButton();
openFrameButton = new JButton();
hideWindowButton = new JButton();
reopenButton = new JButton();
replaceRootPaneButton = new JButton();
openFrameButton = new JButton();
showHiddenWindowButton = new JButton();
reshowButton = new JButton();
revalidateButton = new JButton();
hSpacer1 = new JPanel(null);
closeButton = new JButton();
@@ -331,6 +404,7 @@ public class FlatNativeWindowBorderTest
"[]0" +
"[]0" +
"[]" +
"[]" +
"[]"));
//---- info ----
@@ -368,15 +442,10 @@ public class FlatNativeWindowBorderTest
nativeCheckBox.addActionListener(e -> nativeChanged());
add(nativeCheckBox, "cell 0 3 3 1");
//---- revalidateButton ----
revalidateButton.setText("revalidate");
revalidateButton.addActionListener(e -> revalidateLayout());
add(revalidateButton, "cell 0 3 3 1");
//---- replaceRootPaneButton ----
replaceRootPaneButton.setText("replace rootpane");
replaceRootPaneButton.addActionListener(e -> replaceRootPane());
add(replaceRootPaneButton, "cell 0 3 3 1");
//---- native2CheckBox ----
native2CheckBox.setText("JRootPane.useWindowDecorations");
native2CheckBox.addActionListener(e -> native2Changed());
add(native2CheckBox, "cell 0 3 3 1");
//---- openDialogButton ----
openDialogButton.setText("Open Dialog");
@@ -384,27 +453,47 @@ public class FlatNativeWindowBorderTest
openDialogButton.addActionListener(e -> openDialog());
add(openDialogButton, "cell 0 4 3 1");
//---- openFrameButton ----
openFrameButton.setText("Open Frame");
openFrameButton.setMnemonic('A');
openFrameButton.addActionListener(e -> openFrame());
add(openFrameButton, "cell 0 4 3 1");
//---- hideWindowButton ----
hideWindowButton.setText("Hide");
hideWindowButton.addActionListener(e -> hideWindow());
add(hideWindowButton, "cell 0 4 3 1");
//---- reopenButton ----
reopenButton.setText("Dispose and Reopen");
reopenButton.addActionListener(e -> reopen());
add(reopenButton, "cell 0 4 3 1");
//---- replaceRootPaneButton ----
replaceRootPaneButton.setText("replace rootpane");
replaceRootPaneButton.addActionListener(e -> replaceRootPane());
add(replaceRootPaneButton, "cell 0 4 3 1");
//---- openFrameButton ----
openFrameButton.setText("Open Frame");
openFrameButton.setMnemonic('A');
openFrameButton.addActionListener(e -> openFrame());
add(openFrameButton, "cell 0 5 3 1");
//---- showHiddenWindowButton ----
showHiddenWindowButton.setText("Show hidden");
showHiddenWindowButton.addActionListener(e -> showHiddenWindow());
add(showHiddenWindowButton, "cell 0 4 3 1");
add(hSpacer1, "cell 0 4 3 1,growx");
add(showHiddenWindowButton, "cell 0 5 3 1");
//---- reshowButton ----
reshowButton.setText("Hide and Show");
reshowButton.addActionListener(e -> reshow());
add(reshowButton, "cell 0 5 3 1");
//---- revalidateButton ----
revalidateButton.setText("revalidate");
revalidateButton.addActionListener(e -> revalidateLayout());
add(revalidateButton, "cell 0 5 3 1");
add(hSpacer1, "cell 0 5 3 1,growx");
//---- closeButton ----
closeButton.setText("Close");
closeButton.addActionListener(e -> close());
add(closeButton, "cell 0 4 3 1");
add(closeButton, "cell 0 5 3 1");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
@@ -415,12 +504,15 @@ public class FlatNativeWindowBorderTest
private JCheckBox undecoratedCheckBox;
private JCheckBox fullScreenCheckBox;
private JCheckBox nativeCheckBox;
private JButton revalidateButton;
private JButton replaceRootPaneButton;
private FlatTriStateCheckBox native2CheckBox;
private JButton openDialogButton;
private JButton openFrameButton;
private JButton hideWindowButton;
private JButton reopenButton;
private JButton replaceRootPaneButton;
private JButton openFrameButton;
private JButton showHiddenWindowButton;
private JButton reshowButton;
private JButton revalidateButton;
private JPanel hSpacer1;
private JButton closeButton;
// JFormDesigner - End of variables declaration //GEN-END:variables

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -6,7 +6,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[][][grow,fill]"
"$rowConstraints": "[grow,top]para[]0[]0[][]"
"$rowConstraints": "[grow,top]para[]0[]0[][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -65,17 +65,10 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "revalidateButton"
"text": "revalidate"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "revalidateLayout", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "replaceRootPaneButton"
"text": "replace rootpane"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "replaceRootPane", false ) )
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
name: "native2CheckBox"
"text": "JRootPane.useWindowDecorations"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "native2Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1"
} )
@@ -87,14 +80,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "openFrameButton"
"text": "Open Frame"
"mnemonic": 65
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openFrame", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "hideWindowButton"
"text": "Hide"
@@ -102,28 +87,64 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "reopenButton"
"text": "Dispose and Reopen"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "reopen", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "replaceRootPaneButton"
"text": "replace rootpane"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "replaceRootPane", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "openFrameButton"
"text": "Open Frame"
"mnemonic": 65
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openFrame", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showHiddenWindowButton"
"text": "Show hidden"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showHiddenWindow", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
"value": "cell 0 5 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "reshowButton"
"text": "Hide and Show"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "reshow", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5 3 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "revalidateButton"
"text": "revalidate"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "revalidateLayout", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5 3 1"
} )
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
name: "hSpacer1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1,growx"
"value": "cell 0 5 3 1,growx"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "closeButton"
"text": "Close"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "close", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1"
"value": "cell 0 5 3 1"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 300 )
"size": new java.awt.Dimension( 520, 300 )
} )
}
}

View File

@@ -74,6 +74,10 @@ public class FlatTextComponentsTest
JComboBox<String> comboBox3 = new JComboBox<>();
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JSpinner spinner3 = new JSpinner();
JComboBox<String> comboBox2 = new JComboBox<>();
JComboBox<String> comboBox4 = new JComboBox<>();
JPopupMenu popupMenu1 = new JPopupMenu();
JMenuItem cutMenuItem = new JMenuItem();
JMenuItem copyMenuItem = new JMenuItem();
@@ -97,6 +101,10 @@ public class FlatTextComponentsTest
"[50,fill]" +
"[50,fill]" +
"[]" +
"[]para" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- textFieldLabel ----
@@ -307,6 +315,24 @@ public class FlatTextComponentsTest
spinner1.setName("spinner1");
add(spinner1, "cell 1 7,growx");
//---- spinner2 ----
spinner2.setName("spinner2");
add(spinner2, "cell 1 8,growx,height 40");
//---- spinner3 ----
spinner3.setName("spinner3");
add(spinner3, "cell 1 9,growx,hmax 14");
//---- comboBox2 ----
comboBox2.setEditable(true);
comboBox2.setName("comboBox2");
add(comboBox2, "cell 1 10,growx,height 40");
//---- comboBox4 ----
comboBox4.setEditable(true);
comboBox4.setName("comboBox4");
add(comboBox4, "cell 1 11,growx,hmax 14");
//======== popupMenu1 ========
{
popupMenu1.setName("popupMenu1");

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "13.0.1" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -10,7 +10,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": "[][][::100][100,fill][fill]"
"$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]"
"$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]para[][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -233,9 +233,37 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 8,growx,height 40"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner3"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 9,growx,hmax 14"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox2"
"editable": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 10,growx,height 40"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox4"
"editable": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 11,growx,hmax 14"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 530, 340 )
"size": new java.awt.Dimension( 530, 580 )
} )
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu1"
@@ -252,7 +280,7 @@ new FormModel {
"text": "Paste"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 390 )
"location": new java.awt.Point( 0, 680 )
"size": new java.awt.Dimension( 91, 87 )
} )
}

View File

@@ -25,7 +25,6 @@ import java.util.List;
import java.util.Random;
import javax.swing.*;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import net.miginfocom.swing.*;
/**
@@ -36,17 +35,9 @@ public class FlatWindowDecorationsTest
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
// enable custom window decoration (if LaF supports it)
JFrame.setDefaultLookAndFeelDecorated( true );
JDialog.setDefaultLookAndFeelDecorated( true );
FlatTestFrame frame = FlatTestFrame.create( args, "FlatWindowDecorationsTest" );
frame.applyComponentOrientationToFrame = true;
// WARNING: Do not this in real-world programs.
// frame.setUndecorated( true );
// frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME );
Class<?> cls = FlatWindowDecorationsTest.class;
List<Image> images = Arrays.asList(
new ImageIcon( cls.getResource( "/com/formdev/flatlaf/testing/test16.png" ) ).getImage(),
@@ -75,14 +66,14 @@ public class FlatWindowDecorationsTest
super.addNotify();
Window window = SwingUtilities.windowForComponent( this );
menuBarCheckBox.setEnabled( window instanceof JFrame );
menuBarEmbeddedCheckBox.setEnabled( window instanceof JFrame );
menuBarVisibleCheckBox.setEnabled( window instanceof JFrame );
menuBarCheckBox.setSelected( window instanceof JFrame );
maximizedBoundsCheckBox.setEnabled( window instanceof Frame );
addMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
addGlueButton.setEnabled( menuBarCheckBox.isEnabled() );
removeMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
changeMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
changeTitleButton.setEnabled( menuBarCheckBox.isEnabled() );
boolean windowHasIcons = (window != null && !window.getIconImages().isEmpty());
iconNoneRadioButton.setEnabled( windowHasIcons );
@@ -112,16 +103,19 @@ public class FlatWindowDecorationsTest
private void unifiedBackgroundChanged() {
UIManager.put( "TitlePane.unifiedBackground", unifiedBackgroundCheckBox.isSelected() );
FlatLaf.updateUI();
Window window = SwingUtilities.windowForComponent( this );
if( window != null )
window.repaint();
}
private void menuBarChanged() {
Window window = SwingUtilities.windowForComponent( this );
if( window instanceof JFrame ) {
if( window instanceof JFrame )
((JFrame)window).setJMenuBar( menuBarCheckBox.isSelected() ? menuBar : null );
window.revalidate();
window.repaint();
}
else if( window instanceof JDialog )
((JDialog)window).setJMenuBar( menuBarCheckBox.isSelected() ? menuBar : null );
window.revalidate();
window.repaint();
}
private void menuBarEmbeddedChanged() {
@@ -134,6 +128,58 @@ public class FlatWindowDecorationsTest
menuBar.setVisible( menuBarVisibleCheckBox.isSelected() );
}
private void rightCompChanged() {
removeNonMenusFromMenuBar();
if( rightCompCheckBox.isSelected() ) {
rightStretchCompCheckBox.setSelected( false );
JButton myButton = new JButton( "?" );
myButton.putClientProperty( "JButton.buttonType", "toolBarButton" );
myButton.setFocusable( false );
menuBar.add( Box.createGlue() );
menuBar.add( myButton );
}
menuBar.revalidate();
menuBar.repaint();
}
private void rightStretchCompChanged() {
removeNonMenusFromMenuBar();
if( rightStretchCompCheckBox.isSelected() ) {
rightCompCheckBox.setSelected( false );
menuBar.add( Box.createGlue() );
menuBar.add( new JProgressBar() );
}
menuBar.revalidate();
menuBar.repaint();
}
private void removeNonMenusFromMenuBar() {
Component[] components = menuBar.getComponents();
for( int i = components.length - 1; i >= 0; i-- ) {
if( !(components[i] instanceof JMenu) )
menuBar.remove( i );
else
break;
}
}
private void colorizeTitleBar() {
JRootPane rootPane = getWindowRootPane();
if( rootPane == null )
return;
boolean colorize = colorizeTitleBarCheckBox.isSelected();
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_BACKGROUND, colorize ? Color.green : null );
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_FOREGROUND, colorize ? Color.blue : null );
}
private void colorizeMenuBar() {
boolean colorize = colorizeMenuBarCheckBox.isSelected();
Color menuBarBackground = colorize ? new Color( 0xffccff ) : UIManager.getColor( "MenuBar.background" );
@@ -250,7 +296,7 @@ public class FlatWindowDecorationsTest
private void openDialog() {
Window owner = SwingUtilities.windowForComponent( this );
JDialog dialog = new JDialog( owner, "Dialog", ModalityType.APPLICATION_MODAL );
JDialog dialog = new JDialog( owner, "Dialog", ModalityType.DOCUMENT_MODAL );
dialog.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
dialog.add( new FlatWindowDecorationsTest() );
dialog.pack();
@@ -258,6 +304,17 @@ public class FlatWindowDecorationsTest
dialog.setVisible( true );
}
private void openFrame() {
FlatWindowDecorationsTest comp = new FlatWindowDecorationsTest();
JFrame frame = new JFrame( "Frame" );
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
frame.add( comp );
frame.setJMenuBar( comp.menuBar );
frame.pack();
frame.setLocationRelativeTo( this );
frame.setVisible( true );
}
private void decorationStyleChanged() {
int style;
if( styleFrameRadioButton.isSelected() )
@@ -312,17 +369,20 @@ public class FlatWindowDecorationsTest
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
menuBarCheckBox = new JCheckBox();
unifiedBackgroundCheckBox = new JCheckBox();
rightCompCheckBox = new JCheckBox();
JPanel panel3 = new JPanel();
addMenuButton = new JButton();
JButton addGlueButton = new JButton();
addGlueButton = new JButton();
removeMenuButton = new JButton();
changeMenuButton = new JButton();
JButton changeTitleButton = new JButton();
changeTitleButton = new JButton();
menuBarEmbeddedCheckBox = new JCheckBox();
colorizeMenuBarCheckBox = new JCheckBox();
rightStretchCompCheckBox = new JCheckBox();
menuBarVisibleCheckBox = new JCheckBox();
colorizeMenuBarCheckBox = new JCheckBox();
unifiedBackgroundCheckBox = new JCheckBox();
colorizeMenusCheckBox = new JCheckBox();
colorizeTitleBarCheckBox = new JCheckBox();
resizableCheckBox = new JCheckBox();
maximizedBoundsCheckBox = new JCheckBox();
undecoratedCheckBox = new JCheckBox();
@@ -344,6 +404,7 @@ public class FlatWindowDecorationsTest
iconTestAllRadioButton = new JRadioButton();
iconTestRandomRadioButton = new JRadioButton();
JButton openDialogButton = new JButton();
JButton openFrameButton = new JButton();
menuBar = new JMenuBar();
JMenu fileMenu = new JMenu();
JMenuItem newMenuItem = new JMenuItem();
@@ -381,6 +442,8 @@ public class FlatWindowDecorationsTest
// rows
"para[]0" +
"[]0" +
"[]0" +
"[]0" +
"[]unrel" +
"[]0" +
"[]unrel" +
@@ -394,10 +457,10 @@ public class FlatWindowDecorationsTest
menuBarCheckBox.addActionListener(e -> menuBarChanged());
add(menuBarCheckBox, "cell 0 0");
//---- unifiedBackgroundCheckBox ----
unifiedBackgroundCheckBox.setText("unified background");
unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged());
add(unifiedBackgroundCheckBox, "cell 1 0");
//---- rightCompCheckBox ----
rightCompCheckBox.setText("right aligned component");
rightCompCheckBox.addActionListener(e -> rightCompChanged());
add(rightCompCheckBox, "cell 1 0");
//======== panel3 ========
{
@@ -437,7 +500,7 @@ public class FlatWindowDecorationsTest
changeTitleButton.addActionListener(e -> changeTitle());
panel3.add(changeTitleButton, "cell 0 4");
}
add(panel3, "cell 2 0 1 6,aligny top,growy 0");
add(panel3, "cell 2 0 1 8,aligny top,growy 0");
//---- menuBarEmbeddedCheckBox ----
menuBarEmbeddedCheckBox.setText("embedded menu bar");
@@ -445,10 +508,10 @@ public class FlatWindowDecorationsTest
menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged());
add(menuBarEmbeddedCheckBox, "cell 0 1");
//---- colorizeMenuBarCheckBox ----
colorizeMenuBarCheckBox.setText("colorize menu bar");
colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar());
add(colorizeMenuBarCheckBox, "cell 1 1");
//---- rightStretchCompCheckBox ----
rightStretchCompCheckBox.setText("right aligned stretching component");
rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged());
add(rightStretchCompCheckBox, "cell 1 1");
//---- menuBarVisibleCheckBox ----
menuBarVisibleCheckBox.setText("menu bar visible");
@@ -456,39 +519,54 @@ public class FlatWindowDecorationsTest
menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged());
add(menuBarVisibleCheckBox, "cell 0 2");
//---- colorizeMenuBarCheckBox ----
colorizeMenuBarCheckBox.setText("colorize menu bar");
colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar());
add(colorizeMenuBarCheckBox, "cell 1 2");
//---- unifiedBackgroundCheckBox ----
unifiedBackgroundCheckBox.setText("unified background");
unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged());
add(unifiedBackgroundCheckBox, "cell 0 3");
//---- colorizeMenusCheckBox ----
colorizeMenusCheckBox.setText("colorize menus");
colorizeMenusCheckBox.addActionListener(e -> colorizeMenus());
add(colorizeMenusCheckBox, "cell 1 2");
add(colorizeMenusCheckBox, "cell 1 3");
//---- colorizeTitleBarCheckBox ----
colorizeTitleBarCheckBox.setText("colorize title bar");
colorizeTitleBarCheckBox.addActionListener(e -> colorizeTitleBar());
add(colorizeTitleBarCheckBox, "cell 0 4");
//---- resizableCheckBox ----
resizableCheckBox.setText("resizable");
resizableCheckBox.setSelected(true);
resizableCheckBox.addActionListener(e -> resizableChanged());
add(resizableCheckBox, "cell 0 3");
add(resizableCheckBox, "cell 0 5");
//---- maximizedBoundsCheckBox ----
maximizedBoundsCheckBox.setText("maximized bounds (50,100, 1000,700)");
maximizedBoundsCheckBox.addActionListener(e -> maximizedBoundsChanged());
add(maximizedBoundsCheckBox, "cell 1 3");
add(maximizedBoundsCheckBox, "cell 1 5");
//---- undecoratedCheckBox ----
undecoratedCheckBox.setText("undecorated");
undecoratedCheckBox.addActionListener(e -> undecoratedChanged());
add(undecoratedCheckBox, "cell 0 4");
add(undecoratedCheckBox, "cell 0 6");
//---- fullScreenCheckBox ----
fullScreenCheckBox.setText("full screen");
fullScreenCheckBox.addActionListener(e -> fullScreenChanged());
add(fullScreenCheckBox, "cell 1 4");
add(fullScreenCheckBox, "cell 1 6");
//---- label1 ----
label1.setText("Style:");
add(label1, "cell 0 5");
add(label1, "cell 0 7");
//---- label2 ----
label2.setText("Icon:");
add(label2, "cell 1 5");
add(label2, "cell 1 7");
//======== panel1 ========
{
@@ -553,7 +631,7 @@ public class FlatWindowDecorationsTest
styleFileChooserRadioButton.addActionListener(e -> decorationStyleChanged());
panel1.add(styleFileChooserRadioButton, "cell 0 8");
}
add(panel1, "cell 0 6");
add(panel1, "cell 0 8");
//======== panel2 ========
{
@@ -582,12 +660,18 @@ public class FlatWindowDecorationsTest
iconTestRandomRadioButton.addActionListener(e -> iconChanged());
panel2.add(iconTestRandomRadioButton, "cell 0 2");
}
add(panel2, "cell 1 6");
add(panel2, "cell 1 8");
//---- openDialogButton ----
openDialogButton.setText("Open Dialog");
openDialogButton.addActionListener(e -> openDialog());
add(openDialogButton, "cell 0 7");
add(openDialogButton, "cell 0 9 2 1");
//---- openFrameButton ----
openFrameButton.setText("Open Frame");
openFrameButton.setMnemonic('A');
openFrameButton.addActionListener(e -> openFrame());
add(openFrameButton, "cell 0 9 2 1");
//======== menuBar ========
{
@@ -779,14 +863,19 @@ public class FlatWindowDecorationsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JCheckBox menuBarCheckBox;
private JCheckBox unifiedBackgroundCheckBox;
private JCheckBox rightCompCheckBox;
private JButton addMenuButton;
private JButton addGlueButton;
private JButton removeMenuButton;
private JButton changeMenuButton;
private JButton changeTitleButton;
private JCheckBox menuBarEmbeddedCheckBox;
private JCheckBox colorizeMenuBarCheckBox;
private JCheckBox rightStretchCompCheckBox;
private JCheckBox menuBarVisibleCheckBox;
private JCheckBox colorizeMenuBarCheckBox;
private JCheckBox unifiedBackgroundCheckBox;
private JCheckBox colorizeMenusCheckBox;
private JCheckBox colorizeTitleBarCheckBox;
private JCheckBox resizableCheckBox;
private JCheckBox maximizedBoundsCheckBox;
private JCheckBox undecoratedCheckBox;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -9,7 +9,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": "[left]para[left][fill]"
"$rowConstraints": "para[]0[]0[]unrel[]0[]unrel[][top][]"
"$rowConstraints": "para[]0[]0[]0[]0[]unrel[]0[]unrel[][top][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JCheckBox" ) {
@@ -24,12 +24,12 @@ new FormModel {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "unifiedBackgroundCheckBox"
"text": "unified background"
name: "rightCompCheckBox"
"text": "right aligned component"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedBackgroundChanged", false ) )
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "rightCompChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
@@ -52,6 +52,9 @@ new FormModel {
add( new FormComponent( "javax.swing.JButton" ) {
name: "addGlueButton"
"text": "Add glue"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addGlue", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
@@ -79,12 +82,15 @@ new FormModel {
add( new FormComponent( "javax.swing.JButton" ) {
name: "changeTitleButton"
"text": "Change title"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 6,aligny top,growy 0"
"value": "cell 2 0 1 8,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "menuBarEmbeddedCheckBox"
@@ -98,12 +104,12 @@ new FormModel {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenuBarCheckBox"
"text": "colorize menu bar"
name: "rightStretchCompCheckBox"
"text": "right aligned stretching component"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenuBar", false ) )
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "rightStretchCompChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
@@ -118,6 +124,26 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenuBarCheckBox"
"text": "colorize menu bar"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenuBar", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "unifiedBackgroundCheckBox"
"text": "unified background"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedBackgroundChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenusCheckBox"
"text": "colorize menus"
@@ -126,7 +152,17 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenus", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
"value": "cell 1 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeTitleBarCheckBox"
"text": "colorize title bar"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeTitleBar", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "resizableCheckBox"
@@ -137,7 +173,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "resizableChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
"value": "cell 0 5"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maximizedBoundsCheckBox"
@@ -147,7 +183,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximizedBoundsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
"value": "cell 1 5"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "undecoratedCheckBox"
@@ -157,7 +193,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "undecoratedChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
"value": "cell 0 6"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "fullScreenCheckBox"
@@ -167,19 +203,19 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullScreenChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
"value": "cell 1 6"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "Style:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5"
"value": "cell 0 7"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "Icon:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5"
"value": "cell 1 7"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
@@ -288,7 +324,7 @@ new FormModel {
"value": "cell 0 8"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6"
"value": "cell 0 8"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
@@ -331,14 +367,22 @@ new FormModel {
"value": "cell 0 2"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6"
"value": "cell 1 8"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "openDialogButton"
"text": "Open Dialog"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDialog", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 7"
"value": "cell 0 9 2 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "openFrameButton"
"text": "Open Frame"
"mnemonic": 65
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openFrame", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 9 2 1"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )

View File

@@ -344,6 +344,7 @@ TitlePane.background = #0f0
TitlePane.inactiveBackground = #080
TitlePane.foreground = #00f
TitlePane.inactiveForeground = #fff
TitlePane.borderColor = #f00
#---- ToggleButton ----

View File

@@ -873,6 +873,7 @@ TitlePane.closePressedBackground
TitlePane.closePressedForeground
TitlePane.embeddedForeground
TitlePane.foreground
TitlePane.icon
TitlePane.iconMargins
TitlePane.iconSize
TitlePane.iconifyIcon