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 - name: Cache Gradle cache
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ~/.gradle/caches path: |
~/.gradle/caches
!~/.gradle/caches/modules-2/modules-2.lock
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle restore-keys: ${{ runner.os }}-gradle

View File

@@ -1,6 +1,68 @@
FlatLaf Change Log 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 ## 1.1
#### New features and improvements #### 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) - [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/) - [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. * limitations under the License.
*/ */
val releaseVersion = "1.1" val releaseVersion = "1.1.2"
val developmentVersion = "1.2-SNAPSHOT" val developmentVersion = "1.2-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion

View File

@@ -232,14 +232,63 @@ public interface FlatClientProperties
//---- JRootPane ---------------------------------------------------------- //---- JRootPane ----------------------------------------------------------
/** /**
* Specifies whether the menu bar is embedded into the title pane if custom * Specifies whether FlatLaf native window decorations should be used
* window decorations are enabled. Default is {@code true}. * 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> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
*/ */
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"; 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 ------------------------------------------- //---- JScrollBar / JScrollPane -------------------------------------------
/** /**

View File

@@ -46,6 +46,7 @@ import javax.swing.JDialog;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.LookAndFeel; import javax.swing.LookAndFeel;
import javax.swing.PopupFactory; import javax.swing.PopupFactory;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIDefaults.ActiveValue; import javax.swing.UIDefaults.ActiveValue;
@@ -59,6 +60,7 @@ import javax.swing.text.StyleContext;
import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.HTMLEditorKit;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder; import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
import com.formdev.flatlaf.ui.FlatPopupFactory; import com.formdev.flatlaf.ui.FlatPopupFactory;
import com.formdev.flatlaf.ui.FlatRootPaneUI;
import com.formdev.flatlaf.util.GrayFilter; import com.formdev.flatlaf.util.GrayFilter;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.MultiResolutionImageSupport; import com.formdev.flatlaf.util.MultiResolutionImageSupport;
@@ -157,7 +159,7 @@ public abstract class FlatLaf
*/ */
@Override @Override
public boolean getSupportsWindowDecorations() { public boolean getSupportsWindowDecorations() {
if( SystemInfo.isProjector ) if( SystemInfo.isProjector || SystemInfo.isWebswing || SystemInfo.isWinPE )
return false; return false;
if( SystemInfo.isWindows_10_orLater && if( SystemInfo.isWindows_10_orLater &&
@@ -377,6 +379,12 @@ public abstract class FlatLaf
initIconColors( defaults, isDark() ); initIconColors( defaults, isDark() );
FlatInputMaps.initInputMaps( defaults ); 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 // get addons and sort them by priority
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class ); ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
List<FlatDefaultsAddon> addons = new ArrayList<>(); List<FlatDefaultsAddon> addons = new ArrayList<>();
@@ -438,8 +446,16 @@ public abstract class FlatLaf
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" ); Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" );
if( winFont != null ) if( winFont != null ) {
uiFont = createCompositeFont( winFont.getFamily(), winFont.getStyle(), winFont.getSize() ); 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 ) { } else if( SystemInfo.isMacOS ) {
String fontName; 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() { public static boolean isShowMnemonics() {
return MnemonicHandler.isShowMnemonics(); return MnemonicHandler.isShowMnemonics();
} }
@@ -744,6 +833,10 @@ public abstract class FlatLaf
public Object createValue( UIDefaults table ) { public Object createValue( UIDefaults table ) {
Font defaultFont = UIManager.getFont( "defaultFont" ); 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 ) { if( lastDefaultFont != defaultFont ) {
lastDefaultFont = defaultFont; lastDefaultFont = defaultFont;

View File

@@ -16,6 +16,8 @@
package com.formdev.flatlaf; package com.formdev.flatlaf;
import com.formdev.flatlaf.util.UIScale;
/** /**
* Defines/documents own system properties used in FlatLaf. * 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", * To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
* which has the same syntax as this one. * which has the same syntax as this one.
* <p> * <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> * <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"; String UI_SCALE = "flatlaf.uiScale";
@@ -44,6 +48,17 @@ public interface FlatSystemProperties
*/ */
String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"; 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. * Specifies whether Ubuntu font should be used on Ubuntu Linux.
* By default, if not running in a JetBrains Runtime, the Liberation Sans font * 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"; 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}. * when creating {@code JFrame} or {@code JDialog}.
* <p> * <p>
* Setting this to {@code true} forces using FlatLaf native window decorations * Setting this to {@code true} forces using native window decorations
* even if they are not enabled by the application. * even if they are not enabled by the application.<br>
* Setting this to {@code false} disables using native window decorations.
* <p> * <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> * <p>
* (requires Window 10) * (requires Window 10)
* <p> * <p>
@@ -77,26 +95,32 @@ public interface FlatSystemProperties
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a> * <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
* (based on OpenJDK). * (based on OpenJDK).
* <p> * <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. * 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> * <p>
* (requires Window 10) * (requires Window 10)
* <p> * <p>
* <strong>Allowed Values</strong> {@code false} and {@code true}<br> * <strong>Allowed Values</strong> {@code false} and {@code true}<br>
* <strong>Default</strong> none * <strong>Default</strong> none
*/ */
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"; String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded";
/** /**

View File

@@ -28,6 +28,7 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowListener; import java.awt.event.WindowListener;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.JDialog;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JMenu; import javax.swing.JMenu;
@@ -137,10 +138,17 @@ class MnemonicHandler
// get menu bar and first menu // get menu bar and first menu
Component c = e.getComponent(); Component c = e.getComponent();
JRootPane rootPane = SwingUtilities.getRootPane( c ); JRootPane rootPane = SwingUtilities.getRootPane( c );
Window window = (rootPane != null) ? SwingUtilities.getWindowAncestor( rootPane ) : null;
JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null; JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null;
if( menuBar == null && window instanceof JFrame ) if( menuBar == null ) {
menuBar = ((JFrame)window).getJMenuBar(); // 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; JMenu firstMenu = (menuBar != null) ? menuBar.getMenu( 0 ) : null;
// select first menu and show mnemonics // 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 ) { protected Color getBackground( JComponent c ) {
boolean toolBarButton = isToolBarButton( c );
// selected state
if( ((AbstractButton)c).isSelected() ) { 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 // we assume that toolbar icon is shown disabled
boolean toolBarButton = isToolBarButton( c );
return buttonStateColor( c, return buttonStateColor( c,
toolBarButton ? toolbarSelectedBackground : selectedBackground, toolBarButton ? toolbarSelectedBackground : selectedBackground,
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground, toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
null, null, null,
null,
toolBarButton ? toolbarPressedBackground : pressedBackground ); toolBarButton ? toolbarPressedBackground : pressedBackground );
} }
if( !c.isEnabled() )
return disabledBackground;
// toolbar button // toolbar button
if( isToolBarButton( c ) ) { if( toolBarButton ) {
ButtonModel model = ((AbstractButton)c).getModel();
if( model.isPressed() )
return toolbarPressedBackground;
if( model.isRollover() )
return toolbarHoverBackground;
// use component background if explicitly set
Color bg = c.getBackground(); Color bg = c.getBackground();
if( isCustomBackground( bg ) ) return buttonStateColor( c,
return bg; isCustomBackground( bg ) ? bg : null,
null,
// do not paint background null,
return null; toolbarHoverBackground,
toolbarPressedBackground );
} }
boolean def = isDefaultButton( c ); boolean def = isDefaultButton( c );
return buttonStateColor( c, return buttonStateColor( c,
getBackgroundBase( c, def ), getBackgroundBase( c, def ),
null, disabledBackground,
isCustomBackground( c.getBackground() ) ? null : (def ? defaultFocusedBackground : focusedBackground), isCustomBackground( c.getBackground() ) ? null : (def ? defaultFocusedBackground : focusedBackground),
def ? defaultHoverBackground : hoverBackground, def ? defaultHoverBackground : hoverBackground,
def ? defaultPressedBackground : pressedBackground ); def ? defaultPressedBackground : pressedBackground );
@@ -444,16 +438,18 @@ public class FlatButtonUI
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor, public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
Color focusedColor, Color hoverColor, Color pressedColor ) Color focusedColor, Color hoverColor, Color pressedColor )
{ {
AbstractButton b = (c instanceof AbstractButton) ? (AbstractButton) c : null;
if( !c.isEnabled() ) if( !c.isEnabled() )
return disabledColor; return disabledColor;
if( pressedColor != null && b != null && b.getModel().isPressed() ) if( c instanceof AbstractButton ) {
return pressedColor; ButtonModel model = ((AbstractButton)c).getModel();
if( hoverColor != null && b != null && b.getModel().isRollover() ) if( pressedColor != null && model.isPressed() )
return hoverColor; return pressedColor;
if( hoverColor != null && model.isRollover() )
return hoverColor;
}
if( focusedColor != null && isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c ) ) if( focusedColor != null && isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c ) )
return focusedColor; return focusedColor;

View File

@@ -243,7 +243,24 @@ public class FlatComboBoxUI
public void layoutContainer( Container parent ) { public void layoutContainer( Container parent ) {
super.layoutContainer( 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 // fix editor bounds by subtracting padding
editor.setBounds( FlatUIUtils.subtractInsets( editor.getBounds(), padding ) ); editor.setBounds( FlatUIUtils.subtractInsets( editor.getBounds(), padding ) );
} }

View File

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

View File

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

View File

@@ -70,7 +70,7 @@ public class FlatPopupFactory
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" ); 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 ); return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), contents );
// macOS and Linux adds drop shadow to heavy weight popups // macOS and Linux adds drop shadow to heavy weight popups

View File

@@ -95,7 +95,7 @@ public class FlatRootPaneUI
else else
installBorder(); installBorder();
nativeWindowBorderData = FlatNativeWindowBorder.install( rootPane ); installNativeWindowBorder();
} }
protected void installBorder() { protected void installBorder() {
@@ -110,8 +110,7 @@ public class FlatRootPaneUI
public void uninstallUI( JComponent c ) { public void uninstallUI( JComponent c ) {
super.uninstallUI( c ); super.uninstallUI( c );
FlatNativeWindowBorder.uninstall( rootPane, nativeWindowBorderData ); uninstallNativeWindowBorder();
uninstallClientDecorations(); uninstallClientDecorations();
rootPane = null; rootPane = null;
} }
@@ -137,6 +136,34 @@ public class FlatRootPaneUI
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() ); 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() { protected void installClientDecorations() {
boolean isNativeWindowBorderSupported = FlatNativeWindowBorder.isSupported(); boolean isNativeWindowBorderSupported = FlatNativeWindowBorder.isSupported();
@@ -218,6 +245,10 @@ public class FlatRootPaneUI
installBorder(); installBorder();
break; break;
case FlatClientProperties.USE_WINDOW_DECORATIONS:
updateNativeWindowBorder( rootPane );
break;
case FlatClientProperties.MENU_BAR_EMBEDDED: case FlatClientProperties.MENU_BAR_EMBEDDED:
if( titlePane != null ) { if( titlePane != null ) {
titlePane.menuBarChanged(); titlePane.menuBarChanged();
@@ -225,6 +256,12 @@ public class FlatRootPaneUI
rootPane.repaint(); rootPane.repaint();
} }
break; 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 && (parent instanceof JFrame &&
(((JFrame)parent).getJMenuBar() == null || (((JFrame)parent).getJMenuBar() == null ||
!((JFrame)parent).getJMenuBar().isVisible())) || !((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 editorRect = new Rectangle( r );
Rectangle buttonsRect = new Rectangle( r ); Rectangle buttonsRect = new Rectangle( r );
// make button area square // make button area square (if spinner has preferred height)
int buttonsWidth = r.height; int buttonsWidth = parent.getPreferredSize().height - insets.top - insets.bottom;
buttonsRect.width = buttonsWidth; buttonsRect.width = buttonsWidth;
if( parent.getComponentOrientation().isLeftToRight() ) { if( parent.getComponentOrientation().isLeftToRight() ) {

View File

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

View File

@@ -722,6 +722,13 @@ public class FlatTabbedPaneUI
} }
protected Insets getRealTabAreaInsets( int tabPlacement ) { 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 currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
Insets insets = (Insets) currentTabAreaInsets.clone(); Insets insets = (Insets) currentTabAreaInsets.clone();
@@ -1386,13 +1393,18 @@ public class FlatTabbedPaneUI
} }
protected void ensureSelectedTabIsVisibleLater() { 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( () -> { EventQueue.invokeLater( () -> {
ensureSelectedTabIsVisible(); ensureSelectedTabIsVisible();
} ); } );
} }
protected void ensureSelectedTabIsVisible() { protected void ensureSelectedTabIsVisible() {
if( tabPane == null || tabViewport == null ) if( tabPane == null || tabViewport == null || !tabPane.isDisplayable() )
return; return;
ensureCurrentLayout(); ensureCurrentLayout();

View File

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

View File

@@ -54,6 +54,7 @@ import javax.swing.border.CompoundBorder;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.DerivedColor; import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
@@ -140,6 +141,25 @@ public class FlatUIUtils
return (value instanceof Number) ? ((Number)value).floatValue() : defaultValue; 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 ) { public static boolean isChevron( String arrowType ) {
return !"triangle".equals( arrowType ); return !"triangle".equals( arrowType );
} }
@@ -185,7 +205,8 @@ public class FlatUIUtils
/** /**
* Returns whether the given component is the permanent focus owner and * 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" ) @SuppressWarnings( "unchecked" )
public static boolean isPermanentFocusOwner( Component c ) { public static boolean isPermanentFocusOwner( Component c ) {
@@ -195,12 +216,18 @@ public class FlatUIUtils
Object value = ((JComponent)c).getClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER ); Object value = ((JComponent)c).getClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER );
if( value instanceof Predicate ) { if( value instanceof Predicate ) {
return ((Predicate<JComponent>)value).test( (JComponent) c ) && return ((Predicate<JComponent>)value).test( (JComponent) c ) &&
keyboardFocusManager.getActiveWindow() == SwingUtilities.windowForComponent( c ); isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
} }
} }
return keyboardFocusManager.getPermanentFocusOwner() == c && 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 ) if( SystemInfo.isX86_64 )
libraryName += "_64"; libraryName += "_64";
nativeLibrary = new NativeLibrary( libraryName, nativeLibrary = new NativeLibrary( libraryName, null, true );
FlatWindowsNativeWindowBorder.class.getClassLoader(), true );
} }
// check whether native library was successfully loaded // check whether native library was successfully loaded
@@ -197,6 +196,16 @@ class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null; 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 @Override
public boolean isColorizationColorAffectsBorders() { public boolean isColorizationColorAffectsBorders() {
updateColorization(); updateColorization();
@@ -299,6 +308,18 @@ class FlatWindowsNativeWindowBorder
this.window = window; this.window = window;
hwnd = installImpl( 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() { void uninstall() {
@@ -310,6 +331,8 @@ class FlatWindowsNativeWindowBorder
private native long installImpl( Window window ); private native long installImpl( Window window );
private native void uninstallImpl( long hwnd ); private native void uninstallImpl( long hwnd );
private native void updateFrame( long hwnd );
private native void showWindow( long hwnd, int cmd );
// invoked from native code // invoked from native code
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) { 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.UIManager;
import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.BorderUIResource;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.SystemInfo; 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 // check whether root pane already has a parent, which is the case when switching LaF
Window window = SwingUtilities.windowForComponent( rootPane ); Window window = SwingUtilities.windowForComponent( rootPane );
if( window != null ) { if( window != null ) {
FlatNativeWindowBorder.install( window, FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS ); FlatNativeWindowBorder.install( window );
return null; return null;
} }
@@ -89,7 +88,7 @@ public class JBRCustomDecorations
Container parent = e.getChangedParent(); Container parent = e.getChangedParent();
if( parent instanceof Window ) 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 // remove listener since it is actually not possible to uninstall JBR decorations
// use invokeLater to remove listener to avoid that listener // 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 ) if( !SystemInfo.isJetBrainsJVM_11_orLater || !SystemInfo.isWindows_10_orLater )
return; return;
// check whether disabled via system property
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true ) )
return;
try { try {
Class<?> awtAcessorClass = Class.forName( "sun.awt.AWTAccessor" ); Class<?> awtAcessorClass = Class.forName( "sun.awt.AWTAccessor" );
Class<?> compAccessorClass = Class.forName( "sun.awt.AWTAccessor$ComponentAccessor" ); Class<?> compAccessorClass = Class.forName( "sun.awt.AWTAccessor$ComponentAccessor" );

View File

@@ -42,9 +42,15 @@ public class NativeLibrary
/** /**
* Load native library from given classloader. * 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 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 * @param supported whether the native library is supported on the current platform
*/ */
public NativeLibrary( String libraryName, ClassLoader classLoader, boolean supported ) { public NativeLibrary( String libraryName, ClassLoader classLoader, boolean supported ) {
@@ -68,7 +74,9 @@ public class NativeLibrary
libraryName = decorateLibraryName( libraryName ); libraryName = decorateLibraryName( libraryName );
// find library // find library
URL libraryUrl = classLoader.getResource( libraryName ); URL libraryUrl = (classLoader != null)
? classLoader.getResource( libraryName )
: NativeLibrary.class.getResource( "/" + libraryName );
if( libraryUrl == null ) { if( libraryUrl == null ) {
log( "Library '" + libraryName + "' not found", null ); log( "Library '" + libraryName + "' not found", null );
return false; return false;

View File

@@ -56,6 +56,8 @@ public class SystemInfo
// other // other
/** @since 1.1 */ public static final boolean isProjector; /** @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 { static {
// platforms // platforms
@@ -91,6 +93,8 @@ public class SystemInfo
// other // other
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" ); 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 ) { 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" // apply custom scale factor specified in system property "flatlaf.uiScale"
float customScaleFactor = getCustomScaleFactor(); float customScaleFactor = getCustomScaleFactor();
if( customScaleFactor > 0 ) { if( customScaleFactor > 0 ) {
setUserScaleFactor( customScaleFactor ); setUserScaleFactor( customScaleFactor, false );
return; return;
} }
@@ -230,7 +230,7 @@ public class UIScale
} else } else
newScaleFactor = computeScaleFactor( font ); newScaleFactor = computeScaleFactor( font );
setUserScaleFactor( newScaleFactor ); setUserScaleFactor( newScaleFactor, true );
} }
private static float computeScaleFactor( Font font ) { private static float computeScaleFactor( Font font ) {
@@ -274,7 +274,7 @@ public class UIScale
if( scaleFactor == fontScaleFactor ) if( scaleFactor == fontScaleFactor )
return font; 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 ) ); return new FontUIResource( font.deriveFont( (float) newFontSize ) );
} }
@@ -322,11 +322,18 @@ public class UIScale
/** /**
* Sets the user scale factor. * Sets the user scale factor.
*/ */
private static void setUserScaleFactor( float scaleFactor ) { private static void setUserScaleFactor( float scaleFactor, boolean normalize ) {
if( scaleFactor <= 1f ) if( normalize ) {
scaleFactor = 1f; if( scaleFactor < 1f ) {
else // round scale factor to 1/4 scaleFactor = FlatSystemProperties.getBoolean( FlatSystemProperties.UI_SCALE_ALLOW_SCALE_DOWN, false )
scaleFactor = Math.round( scaleFactor * 4f ) / 4f; ? 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; float oldScaleFactor = UIScale.scaleFactor;
UIScale.scaleFactor = scaleFactor; UIScale.scaleFactor = scaleFactor;

View File

@@ -22,6 +22,28 @@
# - https://www.formdev.com/flatlaf/how-to-customize/ # - 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 ----
Button.startBackground = $Button.background Button.startBackground = $Button.background

View File

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

View File

@@ -475,7 +475,7 @@ public class FlatInspector
f.setAccessible( true ); f.setAccessible( true );
Object ui = f.get( c ); Object ui = f.get( c );
appendRow( buf, "UI", (ui != null ? ui.getClass().getName() : "null") ); appendRow( buf, "UI", (ui != null ? ui.getClass().getName() : "null") );
} catch( NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex ) { } catch( Exception ex ) {
// ignore // 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 java.util.Map;
import javax.swing.LookAndFeel; import javax.swing.LookAndFeel;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIDefaults.ActiveValue; import javax.swing.UIDefaults.ActiveValue;
import com.formdev.flatlaf.FlatDefaultsAddon; import com.formdev.flatlaf.FlatDefaultsAddon;
import com.formdev.flatlaf.FlatLaf; 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 * 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. * (invoked before JIDE overwrites UI defaults) and then restore them in the customizer.
* <p> * <p>
* Do not register this class yourself with JIDE.
* It is automatically registered.
* <p>
* Invoked from {@link LookAndFeelFactory#installJideExtension()}. * Invoked from {@link LookAndFeelFactory#installJideExtension()}.
*/ */
public static class FlatJideUIDefaultsCustomizer public static class FlatJideUIDefaultsCustomizer
@@ -79,6 +83,10 @@ public class FlatJideOssDefaultsAddon
@Override @Override
public void initialize( UIDefaults defaults ) { 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<>(); jideDefaults = new HashMap<>();
for( Map.Entry<Object, Object> e : defaults.entrySet() ) { for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
@@ -96,6 +104,10 @@ public class FlatJideOssDefaultsAddon
@Override @Override
public void customize( UIDefaults defaults ) { 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 ) { if( jideDefaults != null ) {
defaults.putAll( jideDefaults ); defaults.putAll( jideDefaults );
jideDefaults = null; jideDefaults = null;

View File

@@ -183,6 +183,16 @@ public class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null; 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 @Override
public boolean isColorizationColorAffectsBorders() { public boolean isColorizationColorAffectsBorders() {
updateColorization(); updateColorization();
@@ -328,7 +338,16 @@ public class FlatWindowsNativeWindowBorder
defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this ); defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this );
// remove the OS window title bar // 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() { void uninstall() {
@@ -348,7 +367,7 @@ public class FlatWindowsNativeWindowBorder
private void updateFrame() { private void updateFrame() {
// this sends WM_NCCALCSIZE and removes/shows the window title bar // this sends WM_NCCALCSIZE and removes/shows the window title bar
User32.INSTANCE.SetWindowPos( hwnd, hwnd, 0, 0, 0, 0, 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 ) ); 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 ----------------------------------------------- //---- class FlatWndProc fields -----------------------------------------------
int FlatWndProc::initialized = 0; int FlatWndProc::initialized = 0;
@@ -89,9 +103,6 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
fwp->defaultWndProc = reinterpret_cast<WNDPROC>( fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) ); ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) );
// remove the OS window title bar
fwp->updateFrame();
return hwnd; return hwnd;
} }
@@ -109,7 +120,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc ); ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
// show the OS window title bar // show the OS window title bar
fwp->updateFrame(); updateFrame( hwnd );
// cleanup // cleanup
env->DeleteGlobalRef( fwp->obj ); env->DeleteGlobalRef( fwp->obj );
@@ -134,10 +145,10 @@ void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) {
initialized = 1; initialized = 1;
} }
void FlatWndProc::updateFrame() { void FlatWndProc::updateFrame( HWND hwnd ) {
// this sends WM_NCCALCSIZE and removes/shows the window title bar // this sends WM_NCCALCSIZE and removes/shows the window title bar
::SetWindowPos( hwnd, hwnd, 0, 0, 0, 0, ::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 ) { LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {

View File

@@ -25,6 +25,7 @@ class FlatWndProc
public: public:
static HWND install( JNIEnv *env, jobject obj, jobject window ); static HWND install( JNIEnv *env, jobject obj, jobject window );
static void uninstall( JNIEnv *env, jobject obj, HWND hwnd ); static void uninstall( JNIEnv *env, jobject obj, HWND hwnd );
static void updateFrame( HWND hwnd );
private: private:
static int initialized; static int initialized;
@@ -42,7 +43,6 @@ private:
FlatWndProc(); FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj ); static void initIDs( JNIEnv *env, jobject obj );
void updateFrame();
static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK WindowProc( 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 JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_uninstallImpl
(JNIEnv *, jobject, jlong); (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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1175,6 +1175,7 @@ TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResou
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #959595 javax.swing.plaf.ColorUIResource [UI] TitlePane.embeddedForeground #959595 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #bbbbbb 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.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [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.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #595959 javax.swing.plaf.ColorUIResource [UI] TitlePane.embeddedForeground #595959 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #000000 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.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [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 ----
TitlePane.background #00ff00 javax.swing.plaf.ColorUIResource [UI] TitlePane.background #00ff00 javax.swing.plaf.ColorUIResource [UI]
TitlePane.borderColor #ff0000 javax.swing.plaf.ColorUIResource [UI]
TitlePane.buttonMaximizedHeight 22 TitlePane.buttonMaximizedHeight 22
TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI] TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.centerTitle false 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.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResource [UI]
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #0000ff 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.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [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.awt.event.WindowListener;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import javax.swing.*; 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.FlatLightLaf;
import com.formdev.flatlaf.extras.FlatInspector; import com.formdev.flatlaf.extras.FlatInspector;
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox;
import com.formdev.flatlaf.ui.FlatLineBorder; import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder; import com.formdev.flatlaf.util.SystemInfo;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -63,7 +71,7 @@ public class FlatNativeWindowBorderTest
frame.dispose(); frame.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); }, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
frame.pack(); frame.setSize( new Dimension( 800, 600 ) );
frame.setLocationRelativeTo( null ); frame.setLocationRelativeTo( null );
int offset = 20 * Window.getWindows().length; int offset = 20 * Window.getWindows().length;
frame.setLocation( frame.getX() + offset, frame.getY() + offset ); frame.setLocation( frame.getX() + offset, frame.getY() + offset );
@@ -80,7 +88,7 @@ public class FlatNativeWindowBorderTest
dialog.dispose(); dialog.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); }, 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.setLocationRelativeTo( owner );
dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 ); dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 );
dialog.setVisible( true ); dialog.setVisible( true );
@@ -96,7 +104,6 @@ public class FlatNativeWindowBorderTest
hideWindowButton.setEnabled( false ); hideWindowButton.setEnabled( false );
setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) ); setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) );
setPreferredSize( new Dimension( 800, 600 ) );
updateInfo(); updateInfo();
@@ -144,6 +151,26 @@ public class FlatNativeWindowBorderTest
System.out.println( windowId + " windowDeactivated" ); 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() { private void updateInfo() {
@@ -220,6 +247,28 @@ public class FlatNativeWindowBorderTest
(r1.y + r1.height) - (r2.y + r2.height) ); (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() { private void resizableChanged() {
if( window instanceof Frame ) if( window instanceof Frame )
((Frame)window).setResizable( resizableCheckBox.isSelected() ); ((Frame)window).setResizable( resizableCheckBox.isSelected() );
@@ -255,7 +304,11 @@ public class FlatNativeWindowBorderTest
} }
private void nativeChanged() { 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() { 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() { private void close() {
window.dispose(); window.dispose();
} }
@@ -310,12 +380,15 @@ public class FlatNativeWindowBorderTest
undecoratedCheckBox = new JCheckBox(); undecoratedCheckBox = new JCheckBox();
fullScreenCheckBox = new JCheckBox(); fullScreenCheckBox = new JCheckBox();
nativeCheckBox = new JCheckBox(); nativeCheckBox = new JCheckBox();
revalidateButton = new JButton(); native2CheckBox = new FlatTriStateCheckBox();
replaceRootPaneButton = new JButton();
openDialogButton = new JButton(); openDialogButton = new JButton();
openFrameButton = new JButton();
hideWindowButton = new JButton(); hideWindowButton = new JButton();
reopenButton = new JButton();
replaceRootPaneButton = new JButton();
openFrameButton = new JButton();
showHiddenWindowButton = new JButton(); showHiddenWindowButton = new JButton();
reshowButton = new JButton();
revalidateButton = new JButton();
hSpacer1 = new JPanel(null); hSpacer1 = new JPanel(null);
closeButton = new JButton(); closeButton = new JButton();
@@ -331,6 +404,7 @@ public class FlatNativeWindowBorderTest
"[]0" + "[]0" +
"[]0" + "[]0" +
"[]" + "[]" +
"[]" +
"[]")); "[]"));
//---- info ---- //---- info ----
@@ -368,15 +442,10 @@ public class FlatNativeWindowBorderTest
nativeCheckBox.addActionListener(e -> nativeChanged()); nativeCheckBox.addActionListener(e -> nativeChanged());
add(nativeCheckBox, "cell 0 3 3 1"); add(nativeCheckBox, "cell 0 3 3 1");
//---- revalidateButton ---- //---- native2CheckBox ----
revalidateButton.setText("revalidate"); native2CheckBox.setText("JRootPane.useWindowDecorations");
revalidateButton.addActionListener(e -> revalidateLayout()); native2CheckBox.addActionListener(e -> native2Changed());
add(revalidateButton, "cell 0 3 3 1"); add(native2CheckBox, "cell 0 3 3 1");
//---- replaceRootPaneButton ----
replaceRootPaneButton.setText("replace rootpane");
replaceRootPaneButton.addActionListener(e -> replaceRootPane());
add(replaceRootPaneButton, "cell 0 3 3 1");
//---- openDialogButton ---- //---- openDialogButton ----
openDialogButton.setText("Open Dialog"); openDialogButton.setText("Open Dialog");
@@ -384,27 +453,47 @@ public class FlatNativeWindowBorderTest
openDialogButton.addActionListener(e -> openDialog()); openDialogButton.addActionListener(e -> openDialog());
add(openDialogButton, "cell 0 4 3 1"); 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 ----
hideWindowButton.setText("Hide"); hideWindowButton.setText("Hide");
hideWindowButton.addActionListener(e -> hideWindow()); hideWindowButton.addActionListener(e -> hideWindow());
add(hideWindowButton, "cell 0 4 3 1"); 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 ----
showHiddenWindowButton.setText("Show hidden"); showHiddenWindowButton.setText("Show hidden");
showHiddenWindowButton.addActionListener(e -> showHiddenWindow()); showHiddenWindowButton.addActionListener(e -> showHiddenWindow());
add(showHiddenWindowButton, "cell 0 4 3 1"); add(showHiddenWindowButton, "cell 0 5 3 1");
add(hSpacer1, "cell 0 4 3 1,growx");
//---- 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 ----
closeButton.setText("Close"); closeButton.setText("Close");
closeButton.addActionListener(e -> 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 // JFormDesigner - End of component initialization //GEN-END:initComponents
} }
@@ -415,12 +504,15 @@ public class FlatNativeWindowBorderTest
private JCheckBox undecoratedCheckBox; private JCheckBox undecoratedCheckBox;
private JCheckBox fullScreenCheckBox; private JCheckBox fullScreenCheckBox;
private JCheckBox nativeCheckBox; private JCheckBox nativeCheckBox;
private JButton revalidateButton; private FlatTriStateCheckBox native2CheckBox;
private JButton replaceRootPaneButton;
private JButton openDialogButton; private JButton openDialogButton;
private JButton openFrameButton;
private JButton hideWindowButton; private JButton hideWindowButton;
private JButton reopenButton;
private JButton replaceRootPaneButton;
private JButton openFrameButton;
private JButton showHiddenWindowButton; private JButton showHiddenWindowButton;
private JButton reshowButton;
private JButton revalidateButton;
private JPanel hSpacer1; private JPanel hSpacer1;
private JButton closeButton; private JButton closeButton;
// JFormDesigner - End of variables declaration //GEN-END:variables // 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 { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -6,7 +6,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3" "$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[][][grow,fill]" "$columnConstraints": "[][][grow,fill]"
"$rowConstraints": "[grow,top]para[]0[]0[][]" "$rowConstraints": "[grow,top]para[]0[]0[][][]"
} ) { } ) {
name: "this" name: "this"
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
@@ -65,17 +65,10 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1" "value": "cell 0 3 3 1"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
name: "revalidateButton" name: "native2CheckBox"
"text": "revalidate" "text": "JRootPane.useWindowDecorations"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "revalidateLayout", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "native2Changed", 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 ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 3 1" "value": "cell 0 3 3 1"
} ) } )
@@ -87,14 +80,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1" "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" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "hideWindowButton" name: "hideWindowButton"
"text": "Hide" "text": "Hide"
@@ -102,28 +87,64 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1" "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" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "showHiddenWindowButton" name: "showHiddenWindowButton"
"text": "Show hidden" "text": "Show hidden"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showHiddenWindow", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showHiddenWindow", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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" ) { add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
name: "hSpacer1" name: "hSpacer1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "closeButton" name: "closeButton"
"text": "Close" "text": "Close"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "close", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "close", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 3 1" "value": "cell 0 5 3 1"
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 300 ) "size": new java.awt.Dimension( 520, 300 )
} ) } )
} }
} }

View File

@@ -74,6 +74,10 @@ public class FlatTextComponentsTest
JComboBox<String> comboBox3 = new JComboBox<>(); JComboBox<String> comboBox3 = new JComboBox<>();
JLabel spinnerLabel = new JLabel(); JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner(); 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(); JPopupMenu popupMenu1 = new JPopupMenu();
JMenuItem cutMenuItem = new JMenuItem(); JMenuItem cutMenuItem = new JMenuItem();
JMenuItem copyMenuItem = new JMenuItem(); JMenuItem copyMenuItem = new JMenuItem();
@@ -97,6 +101,10 @@ public class FlatTextComponentsTest
"[50,fill]" + "[50,fill]" +
"[50,fill]" + "[50,fill]" +
"[]" + "[]" +
"[]para" +
"[]" +
"[]" +
"[]" +
"[]")); "[]"));
//---- textFieldLabel ---- //---- textFieldLabel ----
@@ -307,6 +315,24 @@ public class FlatTextComponentsTest
spinner1.setName("spinner1"); spinner1.setName("spinner1");
add(spinner1, "cell 1 7,growx"); 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 ========
{ {
popupMenu1.setName("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 { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -10,7 +10,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][::100][100,fill][fill]" "$columnConstraints": "[][][::100][100,fill][fill]"
"$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]" "$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]para[][][][]"
} ) { } ) {
name: "this" name: "this"
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
@@ -233,9 +233,37 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7,growx" "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 ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "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 ) ) { add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu1" name: "popupMenu1"
@@ -252,7 +280,7 @@ new FormModel {
"text": "Paste" "text": "Paste"
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 390 ) "location": new java.awt.Point( 0, 680 )
"size": new java.awt.Dimension( 91, 87 ) "size": new java.awt.Dimension( 91, 87 )
} ) } )
} }

View File

@@ -25,7 +25,6 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import javax.swing.*; import javax.swing.*;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -36,17 +35,9 @@ public class FlatWindowDecorationsTest
{ {
public static void main( String[] args ) { public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> { SwingUtilities.invokeLater( () -> {
// enable custom window decoration (if LaF supports it)
JFrame.setDefaultLookAndFeelDecorated( true );
JDialog.setDefaultLookAndFeelDecorated( true );
FlatTestFrame frame = FlatTestFrame.create( args, "FlatWindowDecorationsTest" ); FlatTestFrame frame = FlatTestFrame.create( args, "FlatWindowDecorationsTest" );
frame.applyComponentOrientationToFrame = true; frame.applyComponentOrientationToFrame = true;
// WARNING: Do not this in real-world programs.
// frame.setUndecorated( true );
// frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME );
Class<?> cls = FlatWindowDecorationsTest.class; Class<?> cls = FlatWindowDecorationsTest.class;
List<Image> images = Arrays.asList( List<Image> images = Arrays.asList(
new ImageIcon( cls.getResource( "/com/formdev/flatlaf/testing/test16.png" ) ).getImage(), new ImageIcon( cls.getResource( "/com/formdev/flatlaf/testing/test16.png" ) ).getImage(),
@@ -75,14 +66,14 @@ public class FlatWindowDecorationsTest
super.addNotify(); super.addNotify();
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
menuBarCheckBox.setEnabled( window instanceof JFrame ); menuBarCheckBox.setSelected( window instanceof JFrame );
menuBarEmbeddedCheckBox.setEnabled( window instanceof JFrame );
menuBarVisibleCheckBox.setEnabled( window instanceof JFrame );
maximizedBoundsCheckBox.setEnabled( window instanceof Frame ); maximizedBoundsCheckBox.setEnabled( window instanceof Frame );
addMenuButton.setEnabled( menuBarCheckBox.isEnabled() ); addMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
addGlueButton.setEnabled( menuBarCheckBox.isEnabled() );
removeMenuButton.setEnabled( menuBarCheckBox.isEnabled() ); removeMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
changeMenuButton.setEnabled( menuBarCheckBox.isEnabled() ); changeMenuButton.setEnabled( menuBarCheckBox.isEnabled() );
changeTitleButton.setEnabled( menuBarCheckBox.isEnabled() );
boolean windowHasIcons = (window != null && !window.getIconImages().isEmpty()); boolean windowHasIcons = (window != null && !window.getIconImages().isEmpty());
iconNoneRadioButton.setEnabled( windowHasIcons ); iconNoneRadioButton.setEnabled( windowHasIcons );
@@ -112,16 +103,19 @@ public class FlatWindowDecorationsTest
private void unifiedBackgroundChanged() { private void unifiedBackgroundChanged() {
UIManager.put( "TitlePane.unifiedBackground", unifiedBackgroundCheckBox.isSelected() ); UIManager.put( "TitlePane.unifiedBackground", unifiedBackgroundCheckBox.isSelected() );
FlatLaf.updateUI(); Window window = SwingUtilities.windowForComponent( this );
if( window != null )
window.repaint();
} }
private void menuBarChanged() { private void menuBarChanged() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
if( window instanceof JFrame ) { if( window instanceof JFrame )
((JFrame)window).setJMenuBar( menuBarCheckBox.isSelected() ? menuBar : null ); ((JFrame)window).setJMenuBar( menuBarCheckBox.isSelected() ? menuBar : null );
window.revalidate(); else if( window instanceof JDialog )
window.repaint(); ((JDialog)window).setJMenuBar( menuBarCheckBox.isSelected() ? menuBar : null );
} window.revalidate();
window.repaint();
} }
private void menuBarEmbeddedChanged() { private void menuBarEmbeddedChanged() {
@@ -134,6 +128,58 @@ public class FlatWindowDecorationsTest
menuBar.setVisible( menuBarVisibleCheckBox.isSelected() ); 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() { private void colorizeMenuBar() {
boolean colorize = colorizeMenuBarCheckBox.isSelected(); boolean colorize = colorizeMenuBarCheckBox.isSelected();
Color menuBarBackground = colorize ? new Color( 0xffccff ) : UIManager.getColor( "MenuBar.background" ); Color menuBarBackground = colorize ? new Color( 0xffccff ) : UIManager.getColor( "MenuBar.background" );
@@ -250,7 +296,7 @@ public class FlatWindowDecorationsTest
private void openDialog() { private void openDialog() {
Window owner = SwingUtilities.windowForComponent( this ); 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.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
dialog.add( new FlatWindowDecorationsTest() ); dialog.add( new FlatWindowDecorationsTest() );
dialog.pack(); dialog.pack();
@@ -258,6 +304,17 @@ public class FlatWindowDecorationsTest
dialog.setVisible( true ); 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() { private void decorationStyleChanged() {
int style; int style;
if( styleFrameRadioButton.isSelected() ) if( styleFrameRadioButton.isSelected() )
@@ -312,17 +369,20 @@ public class FlatWindowDecorationsTest
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
menuBarCheckBox = new JCheckBox(); menuBarCheckBox = new JCheckBox();
unifiedBackgroundCheckBox = new JCheckBox(); rightCompCheckBox = new JCheckBox();
JPanel panel3 = new JPanel(); JPanel panel3 = new JPanel();
addMenuButton = new JButton(); addMenuButton = new JButton();
JButton addGlueButton = new JButton(); addGlueButton = new JButton();
removeMenuButton = new JButton(); removeMenuButton = new JButton();
changeMenuButton = new JButton(); changeMenuButton = new JButton();
JButton changeTitleButton = new JButton(); changeTitleButton = new JButton();
menuBarEmbeddedCheckBox = new JCheckBox(); menuBarEmbeddedCheckBox = new JCheckBox();
colorizeMenuBarCheckBox = new JCheckBox(); rightStretchCompCheckBox = new JCheckBox();
menuBarVisibleCheckBox = new JCheckBox(); menuBarVisibleCheckBox = new JCheckBox();
colorizeMenuBarCheckBox = new JCheckBox();
unifiedBackgroundCheckBox = new JCheckBox();
colorizeMenusCheckBox = new JCheckBox(); colorizeMenusCheckBox = new JCheckBox();
colorizeTitleBarCheckBox = new JCheckBox();
resizableCheckBox = new JCheckBox(); resizableCheckBox = new JCheckBox();
maximizedBoundsCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox();
undecoratedCheckBox = new JCheckBox(); undecoratedCheckBox = new JCheckBox();
@@ -344,6 +404,7 @@ public class FlatWindowDecorationsTest
iconTestAllRadioButton = new JRadioButton(); iconTestAllRadioButton = new JRadioButton();
iconTestRandomRadioButton = new JRadioButton(); iconTestRandomRadioButton = new JRadioButton();
JButton openDialogButton = new JButton(); JButton openDialogButton = new JButton();
JButton openFrameButton = new JButton();
menuBar = new JMenuBar(); menuBar = new JMenuBar();
JMenu fileMenu = new JMenu(); JMenu fileMenu = new JMenu();
JMenuItem newMenuItem = new JMenuItem(); JMenuItem newMenuItem = new JMenuItem();
@@ -381,6 +442,8 @@ public class FlatWindowDecorationsTest
// rows // rows
"para[]0" + "para[]0" +
"[]0" + "[]0" +
"[]0" +
"[]0" +
"[]unrel" + "[]unrel" +
"[]0" + "[]0" +
"[]unrel" + "[]unrel" +
@@ -394,10 +457,10 @@ public class FlatWindowDecorationsTest
menuBarCheckBox.addActionListener(e -> menuBarChanged()); menuBarCheckBox.addActionListener(e -> menuBarChanged());
add(menuBarCheckBox, "cell 0 0"); add(menuBarCheckBox, "cell 0 0");
//---- unifiedBackgroundCheckBox ---- //---- rightCompCheckBox ----
unifiedBackgroundCheckBox.setText("unified background"); rightCompCheckBox.setText("right aligned component");
unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged()); rightCompCheckBox.addActionListener(e -> rightCompChanged());
add(unifiedBackgroundCheckBox, "cell 1 0"); add(rightCompCheckBox, "cell 1 0");
//======== panel3 ======== //======== panel3 ========
{ {
@@ -437,7 +500,7 @@ public class FlatWindowDecorationsTest
changeTitleButton.addActionListener(e -> changeTitle()); changeTitleButton.addActionListener(e -> changeTitle());
panel3.add(changeTitleButton, "cell 0 4"); 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 ----
menuBarEmbeddedCheckBox.setText("embedded menu bar"); menuBarEmbeddedCheckBox.setText("embedded menu bar");
@@ -445,10 +508,10 @@ public class FlatWindowDecorationsTest
menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged()); menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged());
add(menuBarEmbeddedCheckBox, "cell 0 1"); add(menuBarEmbeddedCheckBox, "cell 0 1");
//---- colorizeMenuBarCheckBox ---- //---- rightStretchCompCheckBox ----
colorizeMenuBarCheckBox.setText("colorize menu bar"); rightStretchCompCheckBox.setText("right aligned stretching component");
colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar()); rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged());
add(colorizeMenuBarCheckBox, "cell 1 1"); add(rightStretchCompCheckBox, "cell 1 1");
//---- menuBarVisibleCheckBox ---- //---- menuBarVisibleCheckBox ----
menuBarVisibleCheckBox.setText("menu bar visible"); menuBarVisibleCheckBox.setText("menu bar visible");
@@ -456,39 +519,54 @@ public class FlatWindowDecorationsTest
menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged()); menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged());
add(menuBarVisibleCheckBox, "cell 0 2"); 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 ----
colorizeMenusCheckBox.setText("colorize menus"); colorizeMenusCheckBox.setText("colorize menus");
colorizeMenusCheckBox.addActionListener(e -> colorizeMenus()); 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 ----
resizableCheckBox.setText("resizable"); resizableCheckBox.setText("resizable");
resizableCheckBox.setSelected(true); resizableCheckBox.setSelected(true);
resizableCheckBox.addActionListener(e -> resizableChanged()); resizableCheckBox.addActionListener(e -> resizableChanged());
add(resizableCheckBox, "cell 0 3"); add(resizableCheckBox, "cell 0 5");
//---- maximizedBoundsCheckBox ---- //---- maximizedBoundsCheckBox ----
maximizedBoundsCheckBox.setText("maximized bounds (50,100, 1000,700)"); maximizedBoundsCheckBox.setText("maximized bounds (50,100, 1000,700)");
maximizedBoundsCheckBox.addActionListener(e -> maximizedBoundsChanged()); maximizedBoundsCheckBox.addActionListener(e -> maximizedBoundsChanged());
add(maximizedBoundsCheckBox, "cell 1 3"); add(maximizedBoundsCheckBox, "cell 1 5");
//---- undecoratedCheckBox ---- //---- undecoratedCheckBox ----
undecoratedCheckBox.setText("undecorated"); undecoratedCheckBox.setText("undecorated");
undecoratedCheckBox.addActionListener(e -> undecoratedChanged()); undecoratedCheckBox.addActionListener(e -> undecoratedChanged());
add(undecoratedCheckBox, "cell 0 4"); add(undecoratedCheckBox, "cell 0 6");
//---- fullScreenCheckBox ---- //---- fullScreenCheckBox ----
fullScreenCheckBox.setText("full screen"); fullScreenCheckBox.setText("full screen");
fullScreenCheckBox.addActionListener(e -> fullScreenChanged()); fullScreenCheckBox.addActionListener(e -> fullScreenChanged());
add(fullScreenCheckBox, "cell 1 4"); add(fullScreenCheckBox, "cell 1 6");
//---- label1 ---- //---- label1 ----
label1.setText("Style:"); label1.setText("Style:");
add(label1, "cell 0 5"); add(label1, "cell 0 7");
//---- label2 ---- //---- label2 ----
label2.setText("Icon:"); label2.setText("Icon:");
add(label2, "cell 1 5"); add(label2, "cell 1 7");
//======== panel1 ======== //======== panel1 ========
{ {
@@ -553,7 +631,7 @@ public class FlatWindowDecorationsTest
styleFileChooserRadioButton.addActionListener(e -> decorationStyleChanged()); styleFileChooserRadioButton.addActionListener(e -> decorationStyleChanged());
panel1.add(styleFileChooserRadioButton, "cell 0 8"); panel1.add(styleFileChooserRadioButton, "cell 0 8");
} }
add(panel1, "cell 0 6"); add(panel1, "cell 0 8");
//======== panel2 ======== //======== panel2 ========
{ {
@@ -582,12 +660,18 @@ public class FlatWindowDecorationsTest
iconTestRandomRadioButton.addActionListener(e -> iconChanged()); iconTestRandomRadioButton.addActionListener(e -> iconChanged());
panel2.add(iconTestRandomRadioButton, "cell 0 2"); panel2.add(iconTestRandomRadioButton, "cell 0 2");
} }
add(panel2, "cell 1 6"); add(panel2, "cell 1 8");
//---- openDialogButton ---- //---- openDialogButton ----
openDialogButton.setText("Open Dialog"); openDialogButton.setText("Open Dialog");
openDialogButton.addActionListener(e -> openDialog()); 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 ======== //======== menuBar ========
{ {
@@ -779,14 +863,19 @@ public class FlatWindowDecorationsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JCheckBox menuBarCheckBox; private JCheckBox menuBarCheckBox;
private JCheckBox unifiedBackgroundCheckBox; private JCheckBox rightCompCheckBox;
private JButton addMenuButton; private JButton addMenuButton;
private JButton addGlueButton;
private JButton removeMenuButton; private JButton removeMenuButton;
private JButton changeMenuButton; private JButton changeMenuButton;
private JButton changeTitleButton;
private JCheckBox menuBarEmbeddedCheckBox; private JCheckBox menuBarEmbeddedCheckBox;
private JCheckBox colorizeMenuBarCheckBox; private JCheckBox rightStretchCompCheckBox;
private JCheckBox menuBarVisibleCheckBox; private JCheckBox menuBarVisibleCheckBox;
private JCheckBox colorizeMenuBarCheckBox;
private JCheckBox unifiedBackgroundCheckBox;
private JCheckBox colorizeMenusCheckBox; private JCheckBox colorizeMenusCheckBox;
private JCheckBox colorizeTitleBarCheckBox;
private JCheckBox resizableCheckBox; private JCheckBox resizableCheckBox;
private JCheckBox maximizedBoundsCheckBox; private JCheckBox maximizedBoundsCheckBox;
private JCheckBox undecoratedCheckBox; 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 { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left]para[left][fill]" "$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" name: "this"
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
@@ -24,12 +24,12 @@ new FormModel {
"value": "cell 0 0" "value": "cell 0 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "unifiedBackgroundCheckBox" name: "rightCompCheckBox"
"text": "unified background" "text": "right aligned component"
auxiliary() { auxiliary() {
"JavaCodeGenerator.variableLocal": false "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 ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0" "value": "cell 1 0"
} ) } )
@@ -52,6 +52,9 @@ new FormModel {
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "addGlueButton" name: "addGlueButton"
"text": "Add glue" "text": "Add glue"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addGlue", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addGlue", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1" "value": "cell 0 1"
@@ -79,12 +82,15 @@ new FormModel {
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "changeTitleButton" name: "changeTitleButton"
"text": "Change title" "text": "Change title"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4" "value": "cell 0 4"
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "menuBarEmbeddedCheckBox" name: "menuBarEmbeddedCheckBox"
@@ -98,12 +104,12 @@ new FormModel {
"value": "cell 0 1" "value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenuBarCheckBox" name: "rightStretchCompCheckBox"
"text": "colorize menu bar" "text": "right aligned stretching component"
auxiliary() { auxiliary() {
"JavaCodeGenerator.variableLocal": false "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 ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1" "value": "cell 1 1"
} ) } )
@@ -118,6 +124,26 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2" "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" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenusCheckBox" name: "colorizeMenusCheckBox"
"text": "colorize menus" "text": "colorize menus"
@@ -126,7 +152,17 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenus", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenus", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "resizableCheckBox" name: "resizableCheckBox"
@@ -137,7 +173,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "resizableChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "resizableChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3" "value": "cell 0 5"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maximizedBoundsCheckBox" name: "maximizedBoundsCheckBox"
@@ -147,7 +183,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximizedBoundsChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximizedBoundsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3" "value": "cell 1 5"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "undecoratedCheckBox" name: "undecoratedCheckBox"
@@ -157,7 +193,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "undecoratedChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "undecoratedChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4" "value": "cell 0 6"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "fullScreenCheckBox" name: "fullScreenCheckBox"
@@ -167,19 +203,19 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullScreenChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullScreenChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4" "value": "cell 1 6"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1" name: "label1"
"text": "Style:" "text": "Style:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5" "value": "cell 0 7"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2" name: "label2"
"text": "Icon:" "text": "Icon:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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 ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]" "$columnConstraints": "[fill]"
@@ -288,7 +324,7 @@ new FormModel {
"value": "cell 0 8" "value": "cell 0 8"
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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 ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]" "$columnConstraints": "[fill]"
@@ -331,14 +367,22 @@ new FormModel {
"value": "cell 0 2" "value": "cell 0 2"
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6" "value": "cell 1 8"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "openDialogButton" name: "openDialogButton"
"text": "Open Dialog" "text": "Open Dialog"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDialog", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDialog", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, 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 ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )

View File

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

View File

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