mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-10 22:17:13 -06:00
Compare commits
35 Commits
fonts/inte
...
3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfbd25012a | ||
|
|
063fff2ab4 | ||
|
|
fbdc8d5b99 | ||
|
|
625c0a3321 | ||
|
|
2972300112 | ||
|
|
a8e71895ee | ||
|
|
d7a76081e3 | ||
|
|
fd925a6718 | ||
|
|
4fc890a77c | ||
|
|
b804463b73 | ||
|
|
8f161b4b5a | ||
|
|
c6338169f3 | ||
|
|
6cea24ed9e | ||
|
|
3d8eb9eb66 | ||
|
|
a84aceb1ba | ||
|
|
8adb7e3021 | ||
|
|
bc0d5dc9b5 | ||
|
|
1d935d6659 | ||
|
|
445466acd0 | ||
|
|
30af74f806 | ||
|
|
16ddd100d3 | ||
|
|
c946ec170d | ||
|
|
ca514dd76e | ||
|
|
cf44a5c50b | ||
|
|
91b8c02c7f | ||
|
|
3465fa68b4 | ||
|
|
28278a75a7 | ||
|
|
f68a871dd6 | ||
|
|
93d424cfe1 | ||
|
|
a1adde0888 | ||
|
|
13528b49cb | ||
|
|
f3be3f2d1c | ||
|
|
241fe855cc | ||
|
|
ea2447dcb7 | ||
|
|
f40baed65e |
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -9,6 +9,14 @@ on:
|
||||
- '*'
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.*'
|
||||
- '**/.settings/**'
|
||||
- 'flatlaf-core/svg/**'
|
||||
- 'flatlaf-testing/dumps/**'
|
||||
- 'flatlaf-testing/misc/**'
|
||||
- 'images/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -32,7 +40,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: gradle/wrapper-validation-action@v2
|
||||
if: matrix.java == '8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
|
||||
2
.github/workflows/fonts.yml
vendored
2
.github/workflows/fonts.yml
vendored
@@ -13,6 +13,8 @@ on:
|
||||
- 'flatlaf-fonts/**'
|
||||
- '.github/workflows/fonts.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
- '!**.md'
|
||||
- '!**/.settings/**'
|
||||
|
||||
jobs:
|
||||
Fonts:
|
||||
|
||||
4
.github/workflows/natives.yml
vendored
4
.github/workflows/natives.yml
vendored
@@ -13,6 +13,8 @@ on:
|
||||
- 'flatlaf-natives/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
- '!**.md'
|
||||
- '!**/.settings/**'
|
||||
|
||||
jobs:
|
||||
Natives:
|
||||
@@ -28,7 +30,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: gradle/wrapper-validation-action@v2
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v4
|
||||
|
||||
37
.github/workflows/pr-snapshots.yml
vendored
Normal file
37
.github/workflows/pr-snapshots.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||
|
||||
name: PR Snapshots
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.*'
|
||||
- '**/.settings/**'
|
||||
- 'flatlaf-core/svg/**'
|
||||
- 'flatlaf-testing/dumps/**'
|
||||
- 'flatlaf-testing/misc/**'
|
||||
- 'images/**'
|
||||
|
||||
jobs:
|
||||
snapshot:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Publish PR snapshot to oss.sonatype.org
|
||||
run: >
|
||||
./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||
-Pgithub.event.pull_request.number=${{ github.event.pull_request.number }}
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,18 +1,35 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 3.4-SNAPSHOT
|
||||
## 3.4
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Native libraries: System property `flatlaf.nativeLibraryPath` now supports
|
||||
loading native libraries named the same as on Maven central. Improved log
|
||||
messages for loading fails.
|
||||
- FlatLaf window decorations (Windows 10/11 and Linux): Support "full window
|
||||
content" mode, which allows you to extend the content into the window title
|
||||
bar. (PR #801)
|
||||
- macOS: Support larger window title bar close/minimize/zoom buttons spacing in
|
||||
[full window content](https://www.formdev.com/flatlaf/macos/#full_window_content)
|
||||
mode and introduced "buttons placeholder". (PR #779)
|
||||
- Native libraries:
|
||||
- System property `flatlaf.nativeLibraryPath` now supports loading native
|
||||
libraries named the same as on Maven central.
|
||||
- Published `flatlaf-<version>-no-natives.jar` to Maven Central. This JAR is
|
||||
equal to `flatlaf-<version>.jar`, except that it does not contain the
|
||||
FlatLaf native libraries. The Maven "classifier" to use this JAR is
|
||||
`no-natives`. You need to distribute the FlatLaf native libraries with your
|
||||
application.
|
||||
See https://www.formdev.com/flatlaf/native-libraries/ for more details.
|
||||
- Improved log messages for loading fails.
|
||||
- Fonts: Updated **Inter** to
|
||||
[v4.0](https://github.com/rsms/inter/releases/tag/v4.0).
|
||||
- Table: Select all text in cell editor when starting editing using `F2` key.
|
||||
(issue 652)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- macOS: Setting window background (of undecorated window) to translucent color
|
||||
(alpha < 255) did not show the window translucent. (issue #705)
|
||||
- JIDE CommandMenuBar: Fixed `ClassCastException` when JIDE command bar displays
|
||||
`JideMenu` in popup. (PR #794)
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@ import net.ltgt.gradle.errorprone.errorprone
|
||||
|
||||
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
||||
|
||||
// for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT'
|
||||
val pullRequestNumber = findProperty( "github.event.pull_request.number" )
|
||||
if( pullRequestNumber != null )
|
||||
version = "PR-${pullRequestNumber}-SNAPSHOT"
|
||||
|
||||
|
||||
allprojects {
|
||||
version = rootProject.version
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ tasks.withType<Sign>().configureEach {
|
||||
}
|
||||
|
||||
// check whether parallel build is enabled
|
||||
tasks.withType<PublishToMavenRepository>().configureEach {
|
||||
tasks.withType<AbstractPublishToMaven>().configureEach {
|
||||
doFirst {
|
||||
if( System.getProperty( "org.gradle.parallel" ) == "true" )
|
||||
throw RuntimeException( "Publishing does not work correctly with enabled parallel build. Disable parallel build with VM option '-Dorg.gradle.parallel=false'." )
|
||||
|
||||
@@ -61,6 +61,27 @@ tasks {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
}
|
||||
|
||||
register<Zip>( "jarNoNatives" ) {
|
||||
group = "build"
|
||||
dependsOn( "jar" )
|
||||
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveClassifier.set( "no-natives" )
|
||||
archiveExtension.set( "jar" )
|
||||
destinationDirectory = layout.buildDirectory.dir( "libs" )
|
||||
|
||||
from( zipTree( jar.get().archiveFile.get().asFile ) )
|
||||
exclude( "com/formdev/flatlaf/natives/**" )
|
||||
}
|
||||
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
dependsOn( "jarNoNatives" )
|
||||
}
|
||||
|
||||
withType<Sign>().configureEach {
|
||||
dependsOn( "jarNoNatives" )
|
||||
}
|
||||
|
||||
check {
|
||||
dependsOn( "sigtestCheck" )
|
||||
}
|
||||
@@ -127,6 +148,8 @@ flatlafPublish {
|
||||
|
||||
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
||||
nativeArtifacts = listOf(
|
||||
NativeArtifact( tasks.getByName( "jarNoNatives" ).outputs.files.asPath, "no-natives", "jar" ),
|
||||
|
||||
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
|
||||
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
|
||||
NativeArtifact( "${natives}/flatlaf-windows-arm64.dll", "windows-arm64", "dll" ),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Signature file v4.1
|
||||
#Version 3.3
|
||||
#Version 3.4
|
||||
|
||||
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
|
||||
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
|
||||
@@ -12,7 +12,13 @@ fld public final static java.lang.String BUTTON_TYPE_TOOLBAR_BUTTON = "toolBarBu
|
||||
fld public final static java.lang.String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner"
|
||||
fld public final static java.lang.String COMPONENT_ROUND_RECT = "JComponent.roundRect"
|
||||
fld public final static java.lang.String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT = "FlatLaf.fullWindowContent"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT_BUTTONS_BOUNDS = "FlatLaf.fullWindowContent.buttonsBounds"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER = "FlatLaf.fullWindowContent.buttonsPlaceholder"
|
||||
fld public final static java.lang.String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING = "FlatLaf.macOS.windowButtonsSpacing"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING_LARGE = "large"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING_MEDIUM = "medium"
|
||||
fld public final static java.lang.String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"
|
||||
fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHeight"
|
||||
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
||||
|
||||
@@ -257,19 +257,116 @@ public interface FlatClientProperties
|
||||
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
||||
|
||||
/**
|
||||
* Specifies whether a component in an embedded menu bar should behave as caption
|
||||
* Specifies whether a component shown in a window title bar area should behave as caption
|
||||
* (left-click allows moving window, right-click shows window system menu).
|
||||
* The component does not receive mouse pressed/released/clicked/dragged events,
|
||||
* The caption component does not receive mouse pressed/released/clicked/dragged events,
|
||||
* but it gets mouse entered/exited/moved events.
|
||||
* <p>
|
||||
* Since 3.4, this client property also supports using a function that can check
|
||||
* whether a given location in the component should behave as caption.
|
||||
* Useful for components that do not use mouse input on whole component bounds.
|
||||
*
|
||||
* <pre>{@code
|
||||
* myComponent.putClientProperty( "JComponent.titleBarCaption",
|
||||
* (Function<Point, Boolean>) pt -> {
|
||||
* // parameter pt contains mouse location (in myComponent coordinates)
|
||||
* // return true if the component is not interested in mouse input at the given location
|
||||
* // return false if the component wants process mouse input at the given location
|
||||
* // return null if the component children should be checked
|
||||
* return ...; // check here
|
||||
* } );
|
||||
* }</pre>
|
||||
* <b>Warning</b>:
|
||||
* <ul>
|
||||
* <li>This function is invoked often when mouse is moved over window title bar area
|
||||
* and should therefore return quickly.
|
||||
* <li>This function is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
|
||||
* while processing Windows messages.
|
||||
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
|
||||
* </ul>
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean} or {@link java.util.function.Function}<Point, Boolean>
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
||||
|
||||
|
||||
//---- Panel --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Marks the panel as placeholder for the iconfify/maximize/close buttons
|
||||
* in fullWindowContent mode. See {@link #FULL_WINDOW_CONTENT}.
|
||||
* <p>
|
||||
* If fullWindowContent mode is enabled, the preferred size of the panel is equal
|
||||
* to the size of the iconfify/maximize/close buttons. Otherwise is is {@code 0,0}.
|
||||
* <p>
|
||||
* You're responsible to layout that panel at the top-left or top-right corner,
|
||||
* depending on platform, where the iconfify/maximize/close buttons are located.
|
||||
* <p>
|
||||
* Syntax of the value string is: {@code "win|mac [horizontal|vertical] [zeroInFullScreen] [leftToRight|rightToLeft]"}.
|
||||
* <p>
|
||||
* The string must start with {@code "win"} (for Windows or Linux) or
|
||||
* with {@code "mac"} (for macOS) and specifies the platform where the placeholder
|
||||
* should be used. On macOS, you need the placeholder in the top-left corner,
|
||||
* but on Windows/Linux you need it in the top-right corner. So if your application supports
|
||||
* fullWindowContent mode on both platforms, you can add two placeholders to your layout
|
||||
* and FlatLaf automatically uses only one of them. The other gets size {@code 0,0}.
|
||||
* <p>
|
||||
* Optionally, you can append following options to the value string (separated by space characters):
|
||||
* <ul>
|
||||
* <li>{@code "horizontal"} - preferred height is zero
|
||||
* <li>{@code "vertical"} - preferred width is zero
|
||||
* <li>{@code "zeroInFullScreen"} - in full-screen mode on macOS, preferred size is {@code 0,0}
|
||||
* <li>{@code "leftToRight"} - in right-to-left component orientation, preferred size is {@code 0,0}
|
||||
* <li>{@code "rightToLeft"} - in left-to-right component orientation, preferred size is {@code 0,0}
|
||||
* </ul>
|
||||
*
|
||||
* Example for adding placeholder to top-left corner on macOS:
|
||||
* <pre>{@code
|
||||
* JPanel placeholder = new JPanel();
|
||||
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||
*
|
||||
* JToolBar toolBar = new JToolBar();
|
||||
* // add tool bar items
|
||||
*
|
||||
* JPanel toolBarPanel = new JPanel( new BorderLayout() );
|
||||
* toolBarPanel.add( placeholder, BorderLayout.WEST );
|
||||
* toolBarPanel.add( toolBar, BorderLayout.CENTER );
|
||||
*
|
||||
* frame.getContentPane().add( toolBarPanel, BorderLayout.NORTH );
|
||||
* }</pre>
|
||||
*
|
||||
* Or add placeholder as first item to the tool bar:
|
||||
* <pre>{@code
|
||||
* JPanel placeholder = new JPanel();
|
||||
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||
*
|
||||
* JToolBar toolBar = new JToolBar();
|
||||
* toolBar.add( placeholder );
|
||||
* // add tool bar items
|
||||
*
|
||||
* frame.getContentPane().add( toolBar, BorderLayout.NORTH );
|
||||
* }</pre>
|
||||
*
|
||||
* If a tabbed pane is located at the top, you can add the placeholder
|
||||
* as leading component to that tabbed pane:
|
||||
* <pre>{@code
|
||||
* JPanel placeholder = new JPanel();
|
||||
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||
*
|
||||
* tabbedPane.putClientProperty( FlatClientProperties.TABBED_PANE_LEADING_COMPONENT, placeholder );
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JPanel}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
String FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER = "FlatLaf.fullWindowContent.buttonsPlaceholder";
|
||||
|
||||
|
||||
//---- Popup --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -388,6 +485,46 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||
|
||||
/**
|
||||
* Specifies whether the content pane (and the glass pane) should be extended
|
||||
* into the window title bar area
|
||||
* (requires enabled window decorations). Default is {@code false}.
|
||||
* <p>
|
||||
* On macOS, use client property {@code apple.awt.fullWindowContent}
|
||||
* (see <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">macOS Full window content</a>).
|
||||
* <p>
|
||||
* Setting this enables/disables full window content
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* If {@code true}, the content pane (and the glass pane) is extended into
|
||||
* the title bar area. The window icon and title are hidden.
|
||||
* Only the iconfify/maximize/close buttons stay visible in the upper right corner
|
||||
* (and overlap the content pane).
|
||||
* <p>
|
||||
* The user can left-click-and-drag on the title bar area to move the window,
|
||||
* except when clicking on a component that processes mouse events (e.g. buttons or menus).
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
String FULL_WINDOW_CONTENT = "FlatLaf.fullWindowContent";
|
||||
|
||||
/**
|
||||
* Contains the current bounds of the iconfify/maximize/close buttons
|
||||
* (in root pane coordinates) if fullWindowContent mode is enabled.
|
||||
* Otherwise its value is {@code null}.
|
||||
* <p>
|
||||
* <b>Note</b>: Do not set this client property. It is set by FlatLaf.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.awt.Rectangle}
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
String FULL_WINDOW_CONTENT_BUTTONS_BOUNDS = "FlatLaf.fullWindowContent.buttonsBounds";
|
||||
|
||||
/**
|
||||
* Specifies whether the window icon should be shown in the window title bar
|
||||
* (requires enabled window decorations). Default is UI property {@code TitlePane.showIcon}.
|
||||
@@ -1263,6 +1400,44 @@ public interface FlatClientProperties
|
||||
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
||||
|
||||
|
||||
//---- macOS --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies the spacing around the macOS window close/minimize/zoom buttons.
|
||||
* Useful if <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">full window content</a>
|
||||
* is enabled.
|
||||
* <p>
|
||||
* (requires macOS 10.14+ for "medium" spacing and macOS 11+ for "large" spacing, requires Java 17+)
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #MACOS_WINDOW_BUTTONS_SPACING_MEDIUM} or
|
||||
* {@link #MACOS_WINDOW_BUTTONS_SPACING_LARGE} (requires macOS 11+)
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
String MACOS_WINDOW_BUTTONS_SPACING = "FlatLaf.macOS.windowButtonsSpacing";
|
||||
|
||||
/**
|
||||
* Add medium spacing around the macOS window close/minimize/zoom buttons.
|
||||
*
|
||||
* @see #MACOS_WINDOW_BUTTONS_SPACING
|
||||
* @since 3.4
|
||||
*/
|
||||
String MACOS_WINDOW_BUTTONS_SPACING_MEDIUM = "medium";
|
||||
|
||||
/**
|
||||
* Add large spacing around the macOS window close/minimize/zoom buttons.
|
||||
* <p>
|
||||
* (requires macOS 11+; "medium" is used on older systems)
|
||||
*
|
||||
* @see #MACOS_WINDOW_BUTTONS_SPACING
|
||||
* @since 3.4
|
||||
*/
|
||||
String MACOS_WINDOW_BUTTONS_SPACING_LARGE = "large";
|
||||
|
||||
|
||||
//---- helper methods -----------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -429,7 +429,7 @@ public class FlatFileChooserUI
|
||||
iconFunction = (Function<File, Icon>) UIManager.get( "FileChooser.shortcuts.iconFunction" );
|
||||
|
||||
FileSystemView fsv = fc.getFileSystemView();
|
||||
File[] files = getChooserShortcutPanelFiles( fsv );
|
||||
File[] files = JavaCompatibility2.getChooserShortcutPanelFiles( fsv );
|
||||
if( filesFunction != null )
|
||||
files = filesFunction.apply( files );
|
||||
|
||||
@@ -498,32 +498,6 @@ public class FlatFileChooserUI
|
||||
return button;
|
||||
}
|
||||
|
||||
protected File[] getChooserShortcutPanelFiles( FileSystemView fsv ) {
|
||||
try {
|
||||
if( SystemInfo.isJava_12_orLater ) {
|
||||
Method m = fsv.getClass().getMethod( "getChooserShortcutPanelFiles" );
|
||||
File[] files = (File[]) m.invoke( fsv );
|
||||
|
||||
// on macOS and Linux, files consists only of the user home directory
|
||||
if( files.length == 1 && files[0].equals( new File( System.getProperty( "user.home" ) ) ) )
|
||||
files = new File[0];
|
||||
|
||||
return files;
|
||||
} else if( SystemInfo.isWindows ) {
|
||||
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||
Method m = cls.getMethod( "get", String.class );
|
||||
return (File[]) m.invoke( null, "fileChooserShortcutPanelFolders" );
|
||||
}
|
||||
} catch( IllegalAccessException ex ) {
|
||||
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
protected String getDisplayName( FileSystemView fsv, File file ) {
|
||||
if( displayNameFunction != null ) {
|
||||
String name = displayNameFunction.apply( file );
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
@@ -39,7 +38,6 @@ import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ActionMapUIResource;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||
@@ -144,12 +142,10 @@ public class FlatMenuBarUI
|
||||
protected void installKeyboardActions() {
|
||||
super.installKeyboardActions();
|
||||
|
||||
// get shared action map, used for all menu bars
|
||||
ActionMap map = SwingUtilities.getUIActionMap( menuBar );
|
||||
if( map == null ) {
|
||||
map = new ActionMapUIResource();
|
||||
SwingUtilities.replaceUIActionMap( menuBar, map );
|
||||
}
|
||||
map.put( "takeFocus", new TakeFocus() );
|
||||
if( map != null && !(map.get( "takeFocus" ) instanceof TakeFocusAction) )
|
||||
map.put( "takeFocus", new TakeFocusAction( "takeFocus" ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -365,16 +361,20 @@ public class FlatMenuBarUI
|
||||
}
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
//---- class TakeFocusAction ----------------------------------------------
|
||||
|
||||
/**
|
||||
* Activates the menu bar and shows mnemonics.
|
||||
* On Windows, the popup of the first menu is not shown.
|
||||
* On other platforms, the popup of the first menu is shown.
|
||||
*/
|
||||
private static class TakeFocus
|
||||
extends AbstractAction
|
||||
private static class TakeFocusAction
|
||||
extends FlatUIAction
|
||||
{
|
||||
TakeFocusAction( String name ) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
JMenuBar menuBar = (JMenuBar) e.getSource();
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.security.CodeSource;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.NativeLibrary;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
@@ -177,21 +178,39 @@ class FlatNativeLibrary
|
||||
|
||||
// build library file
|
||||
String libraryName = buildLibraryName( jarFile, classifier, ext );
|
||||
File parent = jarFile.getParentFile();
|
||||
File jarDir = jarFile.getParentFile();
|
||||
|
||||
// check whether native library exists in same directory as jar
|
||||
File libraryFile = new File( parent, libraryName );
|
||||
File libraryFile = new File( jarDir, libraryName );
|
||||
if( libraryFile.isFile() )
|
||||
return libraryFile;
|
||||
|
||||
// if jar is in "lib" directory, then also check whether native library exists
|
||||
// in "../bin" directory
|
||||
if( parent.getName().equalsIgnoreCase( "lib" ) ) {
|
||||
libraryFile = new File( parent.getParentFile(), "bin/" + libraryName );
|
||||
if( jarDir.getName().equalsIgnoreCase( "lib" ) ) {
|
||||
libraryFile = new File( jarDir.getParentFile(), "bin/" + libraryName );
|
||||
if( libraryFile.isFile() )
|
||||
return libraryFile;
|
||||
}
|
||||
|
||||
// special case: support Gradle cache when running in development environment
|
||||
// <user-home>/.gradle/caches/modules-2/files-2.1/com.formdev/flatlaf/<version>/<hash-1>/flatlaf-<version>.jar
|
||||
// <user-home>/.gradle/caches/modules-2/files-2.1/com.formdev/flatlaf/<version>/<hash-2>/flatlaf-<version>-windows-x86_64.dll
|
||||
String path = jarDir.getAbsolutePath().replace( '\\', '/' );
|
||||
if( path.contains( "/.gradle/caches/" ) ) {
|
||||
File versionDir = jarDir.getParentFile();
|
||||
if( libraryName.contains( versionDir.getName() ) ) {
|
||||
File[] dirs = versionDir.listFiles();
|
||||
if( dirs != null ) {
|
||||
for( File dir : dirs ) {
|
||||
libraryFile = new File( dir, libraryName );
|
||||
if( libraryFile.isFile() )
|
||||
return libraryFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// native library not found
|
||||
return null;
|
||||
}
|
||||
@@ -224,6 +243,10 @@ class FlatNativeLibrary
|
||||
private static String buildLibraryName( File jarFile, String classifier, String ext ) {
|
||||
String jarName = jarFile.getName();
|
||||
String jarBasename = jarName.substring( 0, jarName.lastIndexOf( '.' ) );
|
||||
|
||||
// remove classifier "no-natives" (if used)
|
||||
jarBasename = StringUtils.removeTrailing( jarBasename, "-no-natives" );
|
||||
|
||||
return jarBasename
|
||||
+ (jarBasename.contains( "flatlaf" ) ? "" : "-flatlaf")
|
||||
+ '-' + classifier + '.' + ext;
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* Native methods for macOS.
|
||||
@@ -49,8 +51,19 @@ public class FlatNativeMacLibrary
|
||||
* method of this class. Otherwise, the native library may not be loaded.
|
||||
*/
|
||||
public static boolean isLoaded() {
|
||||
return FlatNativeLibrary.isLoaded();
|
||||
return SystemInfo.isMacOS && FlatNativeLibrary.isLoaded();
|
||||
}
|
||||
|
||||
public native static boolean setWindowRoundedBorder( Window window, float radius, float borderWidth, int borderColor );
|
||||
|
||||
/** @since 3.4 */
|
||||
public static final int
|
||||
BUTTONS_SPACING_DEFAULT = 0,
|
||||
BUTTONS_SPACING_MEDIUM = 1,
|
||||
BUTTONS_SPACING_LARGE = 2;
|
||||
|
||||
/** @since 3.4 */ public native static boolean setWindowButtonsSpacing( Window window, int buttonsSpacing );
|
||||
/** @since 3.4 */ public native static Rectangle getWindowButtonsBounds( Window window );
|
||||
/** @since 3.4 */ public native static boolean isWindowFullScreen( Window window );
|
||||
/** @since 3.4 */ public native static boolean toggleWindowFullScreen( Window window );
|
||||
}
|
||||
|
||||
@@ -21,11 +21,12 @@ import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JRootPane;
|
||||
@@ -218,13 +219,13 @@ public class FlatNativeWindowBorder
|
||||
}
|
||||
|
||||
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||
Predicate<Point> captionHitTestCallback, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
||||
{
|
||||
if( !isSupported() )
|
||||
return;
|
||||
|
||||
nativeProvider.updateTitleBarInfo( window, titleBarHeight, hitTestSpots,
|
||||
nativeProvider.updateTitleBarInfo( window, titleBarHeight, captionHitTestCallback,
|
||||
appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
}
|
||||
|
||||
@@ -270,7 +271,7 @@ public class FlatNativeWindowBorder
|
||||
{
|
||||
boolean hasCustomDecoration( Window window );
|
||||
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
||||
void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds );
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@@ -23,6 +24,7 @@ import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPanelUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
@@ -69,6 +71,8 @@ public class FlatPanelUI
|
||||
super.installUI( c );
|
||||
|
||||
c.addPropertyChangeListener( this );
|
||||
if( c.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER ) != null )
|
||||
FullWindowContentSupport.registerPlaceholder( c );
|
||||
|
||||
installStyle( (JPanel) c );
|
||||
}
|
||||
@@ -78,10 +82,20 @@ public class FlatPanelUI
|
||||
super.uninstallUI( c );
|
||||
|
||||
c.removePropertyChangeListener( this );
|
||||
if( c.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER ) != null )
|
||||
FullWindowContentSupport.unregisterPlaceholder( c );
|
||||
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults( JPanel p ) {
|
||||
super.installDefaults( p );
|
||||
|
||||
if( p.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER ) != null )
|
||||
LookAndFeel.installProperty( p, "opaque", false );
|
||||
}
|
||||
|
||||
/** @since 2.0.1 */
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
@@ -98,6 +112,17 @@ public class FlatPanelUI
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER:
|
||||
JPanel p = (JPanel) e.getSource();
|
||||
if( e.getOldValue() != null )
|
||||
FullWindowContentSupport.unregisterPlaceholder( p );
|
||||
if( e.getNewValue() != null )
|
||||
FullWindowContentSupport.registerPlaceholder( p );
|
||||
|
||||
// make panel non-opaque for placeholders
|
||||
LookAndFeel.installProperty( p, "opaque", e.getNewValue() == null );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,4 +187,19 @@ public class FlatPanelUI
|
||||
|
||||
paint( g, c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
Object value = c.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER );
|
||||
if( value != null )
|
||||
return FullWindowContentSupport.getPlaceholderPreferredSize( c, (String) value );
|
||||
|
||||
return super.getPreferredSize( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
if( c.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER ) != null )
|
||||
FullWindowContentSupport.debugPaint( g, c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.LayoutManager2;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
@@ -41,7 +39,6 @@ import javax.swing.JLayeredPane;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.BorderUIResource;
|
||||
@@ -50,6 +47,7 @@ import javax.swing.plaf.RootPaneUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicRootPaneUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -87,8 +85,8 @@ public class FlatRootPaneUI
|
||||
|
||||
private Object nativeWindowBorderData;
|
||||
private LayoutManager oldLayout;
|
||||
private PropertyChangeListener ancestorListener;
|
||||
private ComponentListener componentListener;
|
||||
private ComponentListener macFullWindowContentListener;
|
||||
private PropertyChangeListener macWindowBackgroundListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatRootPaneUI();
|
||||
@@ -106,6 +104,7 @@ public class FlatRootPaneUI
|
||||
installBorder();
|
||||
|
||||
installNativeWindowBorder();
|
||||
macInstallFullWindowContentSupport();
|
||||
}
|
||||
|
||||
protected void installBorder() {
|
||||
@@ -122,6 +121,7 @@ public class FlatRootPaneUI
|
||||
|
||||
uninstallNativeWindowBorder();
|
||||
uninstallClientDecorations();
|
||||
macUninstallFullWindowContentSupport();
|
||||
rootPane = null;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,8 @@ public class FlatRootPaneUI
|
||||
if( background == null || background instanceof UIResource )
|
||||
parent.setBackground( UIManager.getColor( "control" ) );
|
||||
}
|
||||
|
||||
macClearBackgroundForTranslucentWindow( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,55 +176,20 @@ public class FlatRootPaneUI
|
||||
protected void installListeners( JRootPane root ) {
|
||||
super.installListeners( root );
|
||||
|
||||
if( SystemInfo.isJava_9_orLater ) {
|
||||
// On HiDPI screens, where scaling is used, there may be white lines on the
|
||||
// bottom and on the right side of the window when it is initially shown.
|
||||
// This is very disturbing in dark themes, but hard to notice in light themes.
|
||||
// Seems to be a rounding issue when Swing adds dirty region of window
|
||||
// using RepaintManager.nativeAddDirtyRegion().
|
||||
//
|
||||
// Note: Not using a HierarchyListener here, which would be much easier,
|
||||
// because this causes problems with mouse clicks in heavy-weight popups.
|
||||
// Instead, add a listener to the root pane that waits until it is added
|
||||
// to a window, then add a component listener to the window.
|
||||
// See: https://github.com/JFormDesigner/FlatLaf/issues/371
|
||||
ancestorListener = e -> {
|
||||
Object oldValue = e.getOldValue();
|
||||
Object newValue = e.getNewValue();
|
||||
if( newValue instanceof Window ) {
|
||||
if( componentListener == null ) {
|
||||
componentListener = new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentShown( ComponentEvent e ) {
|
||||
// add whole root pane to dirty regions when window is initially shown
|
||||
root.getParent().repaint( root.getX(), root.getY(), root.getWidth(), root.getHeight() );
|
||||
}
|
||||
};
|
||||
}
|
||||
((Window)newValue).addComponentListener( componentListener );
|
||||
} else if( newValue == null && oldValue instanceof Window ) {
|
||||
if( componentListener != null )
|
||||
((Window)oldValue).removeComponentListener( componentListener );
|
||||
}
|
||||
};
|
||||
root.addPropertyChangeListener( "ancestor", ancestorListener );
|
||||
}
|
||||
if( SystemInfo.isMacFullWindowContentSupported )
|
||||
macFullWindowContentListener = FullWindowContentSupport.macInstallListeners( root );
|
||||
macInstallWindowBackgroundListener( root );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( JRootPane root ) {
|
||||
super.uninstallListeners( root );
|
||||
|
||||
if( SystemInfo.isJava_9_orLater ) {
|
||||
if( componentListener != null ) {
|
||||
Window window = SwingUtilities.windowForComponent( root );
|
||||
if( window != null )
|
||||
window.removeComponentListener( componentListener );
|
||||
componentListener = null;
|
||||
}
|
||||
root.removePropertyChangeListener( "ancestor", ancestorListener );
|
||||
ancestorListener = null;
|
||||
if( SystemInfo.isMacFullWindowContentSupported ) {
|
||||
FullWindowContentSupport.macUninstallListeners( root, macFullWindowContentListener );
|
||||
macFullWindowContentListener = null;
|
||||
}
|
||||
macUninstallWindowBackgroundListener( root );
|
||||
}
|
||||
|
||||
/** @since 1.1.2 */
|
||||
@@ -302,19 +269,136 @@ public class FlatRootPaneUI
|
||||
|
||||
// layer title pane under frame content layer to allow placing menu bar over title pane
|
||||
protected final static Integer TITLE_PANE_LAYER = JLayeredPane.FRAME_CONTENT_LAYER - 1;
|
||||
private final static Integer TITLE_PANE_MOUSE_LAYER = JLayeredPane.FRAME_CONTENT_LAYER - 2;
|
||||
|
||||
// for fullWindowContent mode, layer title pane over frame content layer to allow placing title bar buttons over content
|
||||
/** @since 3.4 */
|
||||
protected final static Integer TITLE_PANE_FULL_WINDOW_CONTENT_LAYER = JLayeredPane.FRAME_CONTENT_LAYER + 1;
|
||||
|
||||
private Integer getLayerForTitlePane() {
|
||||
return isFullWindowContent( rootPane ) ? TITLE_PANE_FULL_WINDOW_CONTENT_LAYER : TITLE_PANE_LAYER;
|
||||
}
|
||||
|
||||
protected void setTitlePane( FlatTitlePane newTitlePane ) {
|
||||
JLayeredPane layeredPane = rootPane.getLayeredPane();
|
||||
|
||||
if( titlePane != null )
|
||||
if( titlePane != null ) {
|
||||
layeredPane.remove( titlePane );
|
||||
layeredPane.remove( titlePane.mouseLayer );
|
||||
}
|
||||
|
||||
if( newTitlePane != null )
|
||||
layeredPane.add( newTitlePane, TITLE_PANE_LAYER );
|
||||
if( newTitlePane != null ) {
|
||||
layeredPane.add( newTitlePane, getLayerForTitlePane() );
|
||||
layeredPane.add( newTitlePane.mouseLayer, TITLE_PANE_MOUSE_LAYER );
|
||||
}
|
||||
|
||||
titlePane = newTitlePane;
|
||||
}
|
||||
|
||||
private void macInstallFullWindowContentSupport() {
|
||||
if( !SystemInfo.isMacOS )
|
||||
return;
|
||||
|
||||
// set window buttons spacing
|
||||
if( isMacButtonsSpacingSupported() && rootPane.isDisplayable() ) {
|
||||
int buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_DEFAULT;
|
||||
String value = (String) rootPane.getClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING );
|
||||
if( value != null ) {
|
||||
switch( value ) {
|
||||
case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_MEDIUM:
|
||||
buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_MEDIUM;
|
||||
break;
|
||||
|
||||
case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_LARGE:
|
||||
buttonsSpacing = FlatNativeMacLibrary.BUTTONS_SPACING_LARGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FlatNativeMacLibrary.setWindowButtonsSpacing( getParentWindow( rootPane ), buttonsSpacing );
|
||||
}
|
||||
|
||||
// update buttons bounds client property
|
||||
FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty( rootPane );
|
||||
}
|
||||
|
||||
private void macUninstallFullWindowContentSupport() {
|
||||
if( !SystemInfo.isMacOS )
|
||||
return;
|
||||
|
||||
// do not uninstall when switching to another FlatLaf theme
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf )
|
||||
return;
|
||||
|
||||
// reset window buttons spacing
|
||||
if( isMacButtonsSpacingSupported() )
|
||||
FlatNativeMacLibrary.setWindowButtonsSpacing( getParentWindow( rootPane ), FlatNativeMacLibrary.BUTTONS_SPACING_DEFAULT );
|
||||
|
||||
// remove buttons bounds client property
|
||||
FullWindowContentSupport.macUninstallFullWindowContentButtonsBoundsProperty( rootPane );
|
||||
}
|
||||
|
||||
private boolean isMacButtonsSpacingSupported() {
|
||||
return SystemInfo.isMacOS && SystemInfo.isJava_17_orLater && FlatNativeMacLibrary.isLoaded();
|
||||
}
|
||||
|
||||
private void macInstallWindowBackgroundListener( JRootPane c ) {
|
||||
if( !SystemInfo.isMacOS )
|
||||
return;
|
||||
|
||||
Window window = getParentWindow( c );
|
||||
if( window != null && macWindowBackgroundListener == null ) {
|
||||
macWindowBackgroundListener = e -> macClearBackgroundForTranslucentWindow( c );
|
||||
window.addPropertyChangeListener( "background", macWindowBackgroundListener );
|
||||
}
|
||||
}
|
||||
|
||||
private void macUninstallWindowBackgroundListener( JRootPane c ) {
|
||||
if( !SystemInfo.isMacOS )
|
||||
return;
|
||||
|
||||
Window window = getParentWindow( c );
|
||||
if( window != null && macWindowBackgroundListener != null ) {
|
||||
window.removePropertyChangeListener( "background", macWindowBackgroundListener );
|
||||
macWindowBackgroundListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When setting window background to translucent color (alpha < 255),
|
||||
* Swing paints that window translucent on Windows and Linux, but not on macOS.
|
||||
* The reason for this is that FlatLaf sets the background color of the root pane,
|
||||
* and Swing behaves a bit differently on macOS than on other platforms in that case.
|
||||
* Other L&Fs do not set root pane background, which is {@code null} by default.
|
||||
* <p>
|
||||
* To fix this problem, set the root pane background to {@code null}
|
||||
* if windows uses a translucent background.
|
||||
*/
|
||||
private void macClearBackgroundForTranslucentWindow( JRootPane c ) {
|
||||
if( !SystemInfo.isMacOS )
|
||||
return;
|
||||
|
||||
Window window = getParentWindow( c );
|
||||
if( window != null ) {
|
||||
Color windowBackground = window.getBackground();
|
||||
if( windowBackground != null &&
|
||||
windowBackground.getAlpha() < 255 &&
|
||||
c.getBackground() instanceof UIResource )
|
||||
{
|
||||
// clear root pane background
|
||||
c.setBackground( null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Window getParentWindow( JRootPane c ) {
|
||||
// not using SwingUtilities.windowForComponent() or SwingUtilities.getWindowAncestor()
|
||||
// here because root panes may be nested and used anywhere (e.g. in JInternalFrame)
|
||||
// but we're only interested in the "root" root pane, which is a direct child of the window
|
||||
Container parent = c.getParent();
|
||||
return (parent instanceof Window) ? (Window) parent : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
@@ -359,6 +443,21 @@ public class FlatRootPaneUI
|
||||
titlePane.titleBarColorsChanged();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.FULL_WINDOW_CONTENT:
|
||||
if( titlePane != null ) {
|
||||
rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() );
|
||||
titlePane.updateIcon();
|
||||
titlePane.updateVisibility();
|
||||
titlePane.updateFullWindowContentButtonsBoundsProperty();
|
||||
}
|
||||
FullWindowContentSupport.revalidatePlaceholders( rootPane );
|
||||
rootPane.revalidate();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS:
|
||||
FullWindowContentSupport.revalidatePlaceholders( rootPane );
|
||||
break;
|
||||
|
||||
case FlatClientProperties.GLASS_PANE_FULL_HEIGHT:
|
||||
rootPane.revalidate();
|
||||
break;
|
||||
@@ -367,14 +466,43 @@ public class FlatRootPaneUI
|
||||
if( rootPane.isDisplayable() )
|
||||
throw new IllegalComponentStateException( "The client property 'Window.style' must be set before the window becomes displayable." );
|
||||
break;
|
||||
|
||||
case "ancestor":
|
||||
if( e.getNewValue() instanceof Window )
|
||||
macClearBackgroundForTranslucentWindow( rootPane );
|
||||
|
||||
macUninstallWindowBackgroundListener( rootPane );
|
||||
macInstallWindowBackgroundListener( rootPane );
|
||||
|
||||
// FlatNativeMacLibrary.setWindowButtonsSpacing() and
|
||||
// FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty()
|
||||
// require a native window, but setting the client properties
|
||||
// "apple.awt.fullWindowContent" or FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING
|
||||
// is usually done before the native window is created
|
||||
// --> try again when native window is created
|
||||
if( e.getNewValue() instanceof Window )
|
||||
macInstallFullWindowContentSupport();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING:
|
||||
macInstallFullWindowContentSupport();
|
||||
break;
|
||||
|
||||
case "apple.awt.fullWindowContent":
|
||||
if( SystemInfo.isMacFullWindowContentSupported )
|
||||
FullWindowContentSupport.macUpdateFullWindowContentButtonsBoundsProperty( rootPane );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 3.4 */
|
||||
protected static boolean isFullWindowContent( JRootPane rootPane ) {
|
||||
return FlatClientProperties.clientPropertyBoolean( rootPane, FlatClientProperties.FULL_WINDOW_CONTENT, false );
|
||||
}
|
||||
|
||||
protected static boolean isMenuBarEmbedded( JRootPane rootPane ) {
|
||||
RootPaneUI ui = rootPane.getUI();
|
||||
return ui instanceof FlatRootPaneUI &&
|
||||
((FlatRootPaneUI)ui).titlePane != null &&
|
||||
((FlatRootPaneUI)ui).titlePane.isMenuBarEmbedded();
|
||||
FlatTitlePane titlePane = getTitlePane( rootPane );
|
||||
return titlePane != null && titlePane.isMenuBarEmbedded();
|
||||
}
|
||||
|
||||
/** @since 2.4 */
|
||||
@@ -410,23 +538,21 @@ public class FlatRootPaneUI
|
||||
private Dimension computeLayoutSize( Container parent, Function<Component, Dimension> getSizeFunc ) {
|
||||
JRootPane rootPane = (JRootPane) parent;
|
||||
|
||||
Dimension titlePaneSize = (titlePane != null)
|
||||
? getSizeFunc.apply( titlePane )
|
||||
: new Dimension();
|
||||
Dimension contentSize = (rootPane.getContentPane() != null)
|
||||
? getSizeFunc.apply( rootPane.getContentPane() )
|
||||
: rootPane.getSize();
|
||||
: rootPane.getSize(); // same as in JRootPane.RootLayout.preferredLayoutSize()
|
||||
|
||||
int width = contentSize.width; // title pane width is not considered here
|
||||
int height = titlePaneSize.height + contentSize.height;
|
||||
int height = contentSize.height;
|
||||
if( titlePane != null && !isFullWindowContent( rootPane ) )
|
||||
height += getSizeFunc.apply( titlePane ).height;
|
||||
if( titlePane == null || !titlePane.isMenuBarEmbedded() ) {
|
||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||
Dimension menuBarSize = (menuBar != null && menuBar.isVisible())
|
||||
? getSizeFunc.apply( menuBar )
|
||||
: new Dimension();
|
||||
|
||||
width = Math.max( width, menuBarSize.width );
|
||||
height += menuBarSize.height;
|
||||
if( menuBar != null && menuBar.isVisible() ) {
|
||||
Dimension menuBarSize = getSizeFunc.apply( menuBar );
|
||||
width = Math.max( width, menuBarSize.width );
|
||||
height += menuBarSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
Insets insets = rootPane.getInsets();
|
||||
@@ -451,12 +577,23 @@ public class FlatRootPaneUI
|
||||
if( rootPane.getLayeredPane() != null )
|
||||
rootPane.getLayeredPane().setBounds( x, y, width, height );
|
||||
|
||||
// title pane
|
||||
// title pane (is a child of layered pane)
|
||||
int nextY = 0;
|
||||
if( titlePane != null ) {
|
||||
int prefHeight = !isFullScreen ? titlePane.getPreferredSize().height : 0;
|
||||
titlePane.setBounds( 0, 0, width, prefHeight );
|
||||
nextY += prefHeight;
|
||||
boolean isFullWindowContent = isFullWindowContent( rootPane );
|
||||
if( isFullWindowContent && !UIManager.getBoolean( FlatTitlePane.KEY_DEBUG_SHOW_RECTANGLES ) ) {
|
||||
// place title bar into top-right corner
|
||||
int tw = Math.min( titlePane.getPreferredSize().width, width );
|
||||
int tx = titlePane.getComponentOrientation().isLeftToRight() ? width - tw : 0;
|
||||
titlePane.setBounds( tx, 0, tw, prefHeight );
|
||||
} else
|
||||
titlePane.setBounds( 0, 0, width, prefHeight );
|
||||
|
||||
titlePane.mouseLayer.setBounds( 0, 0, width, prefHeight );
|
||||
|
||||
if( !isFullWindowContent )
|
||||
nextY += prefHeight;
|
||||
}
|
||||
|
||||
// glass pane
|
||||
@@ -467,7 +604,7 @@ public class FlatRootPaneUI
|
||||
rootPane.getGlassPane().setBounds( x, y + offset, width, height - offset );
|
||||
}
|
||||
|
||||
// menu bar
|
||||
// menu bar (is a child of layered pane)
|
||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||
if( menuBar != null && menuBar.isVisible() ) {
|
||||
boolean embedded = !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded();
|
||||
@@ -475,13 +612,23 @@ public class FlatRootPaneUI
|
||||
titlePane.validate();
|
||||
menuBar.setBounds( titlePane.getMenuBarBounds() );
|
||||
} else {
|
||||
int mx = 0;
|
||||
int mw = width;
|
||||
if( titlePane != null && isFullWindowContent( rootPane ) ) {
|
||||
// make menu bar width smaller to avoid that it overlaps title bar buttons
|
||||
int tw = Math.min( titlePane.getPreferredSize().width, width );
|
||||
mw -= tw;
|
||||
if( !titlePane.getComponentOrientation().isLeftToRight() )
|
||||
mx = tw;
|
||||
}
|
||||
|
||||
Dimension prefSize = menuBar.getPreferredSize();
|
||||
menuBar.setBounds( 0, nextY, width, prefSize.height );
|
||||
menuBar.setBounds( mx, nextY, mw, prefSize.height );
|
||||
nextY += prefSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
// content pane
|
||||
// content pane (is a child of layered pane)
|
||||
Container contentPane = rootPane.getContentPane();
|
||||
if( contentPane != null )
|
||||
contentPane.setBounds( 0, nextY, width, Math.max( height - nextY, 0 ) );
|
||||
|
||||
@@ -84,7 +84,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatSplitPaneUI
|
||||
extends BasicSplitPaneUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||
{
|
||||
@Styleable protected String arrowType;
|
||||
/** @since 3.3 */ @Styleable protected Color draggingColor;
|
||||
@@ -227,6 +227,15 @@ public class FlatSplitPaneUI
|
||||
((FlatSplitPaneDivider)divider).paintStyle( g, x, y, width, height );
|
||||
}
|
||||
|
||||
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||
|
||||
/** @since 3.4 */
|
||||
@Override
|
||||
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||
// necessary because BasicSplitPaneDivider adds some mouse listeners for dragging divider
|
||||
return null; // check children
|
||||
}
|
||||
|
||||
//---- class FlatSplitPaneDivider -----------------------------------------
|
||||
|
||||
protected class FlatSplitPaneDivider
|
||||
|
||||
@@ -182,7 +182,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatTabbedPaneUI
|
||||
extends BasicTabbedPaneUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||
{
|
||||
// tab type
|
||||
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
||||
@@ -2300,6 +2300,17 @@ debug*/
|
||||
return (rects[last].y + rects[last].height) - rects[0].y;
|
||||
}
|
||||
|
||||
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||
|
||||
/** @since 3.4 */
|
||||
@Override
|
||||
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||
if( tabForCoordinate( tabPane, x, y ) >= 0 )
|
||||
return false;
|
||||
|
||||
return null; // check children
|
||||
}
|
||||
|
||||
//---- class TabCloseButton -----------------------------------------------
|
||||
|
||||
private static class TabCloseButton
|
||||
@@ -3985,10 +3996,8 @@ debug*/
|
||||
//---- class RunWithOriginalLayoutManagerDelegateAction -------------------
|
||||
|
||||
private static class RunWithOriginalLayoutManagerDelegateAction
|
||||
implements Action
|
||||
extends FlatUIAction
|
||||
{
|
||||
private final Action delegate;
|
||||
|
||||
static void install( ActionMap map, String key ) {
|
||||
Action oldAction = map.get( key );
|
||||
if( oldAction == null || oldAction instanceof RunWithOriginalLayoutManagerDelegateAction )
|
||||
@@ -3998,24 +4007,9 @@ debug*/
|
||||
}
|
||||
|
||||
private RunWithOriginalLayoutManagerDelegateAction( Action delegate ) {
|
||||
this.delegate = delegate;
|
||||
super( delegate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue( String key ) {
|
||||
return delegate.getValue( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return delegate.isEnabled();
|
||||
}
|
||||
|
||||
@Override public void putValue( String key, Object value ) {}
|
||||
@Override public void setEnabled( boolean b ) {}
|
||||
@Override public void addPropertyChangeListener( PropertyChangeListener listener ) {}
|
||||
@Override public void removePropertyChangeListener( PropertyChangeListener listener ) {}
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
JTabbedPane tabbedPane = (JTabbedPane) e.getSource();
|
||||
|
||||
@@ -24,15 +24,19 @@ import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingConstants;
|
||||
@@ -89,6 +93,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Table.selectionInactiveBackground Color
|
||||
* @uiDefault Table.selectionInactiveForeground Color
|
||||
* @uiDefault Table.paintOutsideAlternateRows boolean
|
||||
* @uiDefault Table.editorSelectAllOnStartEditing boolean
|
||||
*
|
||||
* <!-- FlatTableCellBorder -->
|
||||
*
|
||||
@@ -284,6 +289,18 @@ public class FlatTableUI
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installKeyboardActions() {
|
||||
super.installKeyboardActions();
|
||||
|
||||
if( UIManager.getBoolean( "Table.editorSelectAllOnStartEditing" ) ) {
|
||||
// get shared action map, used for all tables
|
||||
ActionMap map = SwingUtilities.getUIActionMap( table );
|
||||
if( map != null )
|
||||
StartEditingAction.install( map, "startEditing" );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
@@ -579,4 +596,36 @@ public class FlatTableUI
|
||||
selected = (value != null && (Boolean) value);
|
||||
}
|
||||
}
|
||||
|
||||
//---- class StartEditingAction -------------------------------------------
|
||||
|
||||
private static class StartEditingAction
|
||||
extends FlatUIAction
|
||||
{
|
||||
static void install( ActionMap map, String key ) {
|
||||
Action oldAction = map.get( key );
|
||||
if( oldAction == null || oldAction instanceof StartEditingAction )
|
||||
return; // not found or already installed
|
||||
|
||||
map.put( key, new StartEditingAction( oldAction ) );
|
||||
}
|
||||
|
||||
private StartEditingAction( Action delegate ) {
|
||||
super( delegate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
JTable table = (JTable) e.getSource();
|
||||
|
||||
Component oldEditorComp = table.getEditorComponent();
|
||||
|
||||
delegate.actionPerformed( e );
|
||||
|
||||
// select all text in editor if editing starts with F2 key
|
||||
Component editorComp = table.getEditorComponent();
|
||||
if( oldEditorComp == null && editorComp instanceof JTextField )
|
||||
((JTextField)editorComp).selectAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
@@ -46,9 +47,9 @@ import java.awt.event.WindowEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
@@ -57,7 +58,6 @@ import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JPanel;
|
||||
@@ -66,6 +66,7 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.AbstractBorder;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder;
|
||||
@@ -98,7 +99,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.showIconBesideTitle boolean
|
||||
* @uiDefault TitlePane.menuBarTitleGap int
|
||||
* @uiDefault TitlePane.menuBarTitleMinimumGap int
|
||||
* @uiDefault TitlePane.menuBarResizeHeight int
|
||||
* @uiDefault TitlePane.closeIcon Icon
|
||||
* @uiDefault TitlePane.iconifyIcon Icon
|
||||
* @uiDefault TitlePane.maximizeIcon Icon
|
||||
@@ -109,7 +109,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatTitlePane
|
||||
extends JComponent
|
||||
{
|
||||
private static final String KEY_DEBUG_SHOW_RECTANGLES = "FlatLaf.debug.titlebar.showRectangles";
|
||||
static final String KEY_DEBUG_SHOW_RECTANGLES = "FlatLaf.debug.titlebar.showRectangles";
|
||||
|
||||
/** @since 2.5 */ protected final Font titleFont;
|
||||
protected final Color activeBackground;
|
||||
@@ -131,7 +131,6 @@ public class FlatTitlePane
|
||||
/** @since 2.4 */ protected final boolean showIconBesideTitle;
|
||||
protected final int menuBarTitleGap;
|
||||
/** @since 2.4 */ protected final int menuBarTitleMinimumGap;
|
||||
/** @since 2.4 */ protected final int menuBarResizeHeight;
|
||||
|
||||
protected final JRootPane rootPane;
|
||||
protected final String windowStyle;
|
||||
@@ -150,6 +149,23 @@ public class FlatTitlePane
|
||||
|
||||
private final Handler handler;
|
||||
|
||||
/**
|
||||
* This panel handles mouse events if FlatLaf window decorations are used
|
||||
* without native window border. E.g. on Linux.
|
||||
* <p>
|
||||
* This panel usually has same bounds as the title pane,
|
||||
* except if fullWindowContent mode is enabled.
|
||||
* <p>
|
||||
* This panel is not a child of the title pane.
|
||||
* Instead it is added by FlatRootPaneUI to the layered pane at a layer
|
||||
* under the title pane and under the frame content.
|
||||
* The separation is necessary for fullWindowContent mode, where the title pane
|
||||
* is layered over the frame content (for title pane buttons), but the mousePanel
|
||||
* needs to be layered under the frame content so that components on content pane
|
||||
* can receive mouse events when located in title area.
|
||||
*/
|
||||
final JPanel mouseLayer;
|
||||
|
||||
public FlatTitlePane( JRootPane rootPane ) {
|
||||
this.rootPane = rootPane;
|
||||
|
||||
@@ -178,7 +194,6 @@ public class FlatTitlePane
|
||||
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
|
||||
menuBarTitleGap = FlatUIUtils.getSubUIInt( "TitlePane.menuBarTitleGap", windowStyle, 40 );
|
||||
menuBarTitleMinimumGap = FlatUIUtils.getSubUIInt( "TitlePane.menuBarTitleMinimumGap", windowStyle, 12 );
|
||||
menuBarResizeHeight = FlatUIUtils.getSubUIInt( "TitlePane.menuBarResizeHeight", windowStyle, 4 );
|
||||
|
||||
|
||||
handler = createHandler();
|
||||
@@ -187,11 +202,10 @@ public class FlatTitlePane
|
||||
addSubComponents();
|
||||
activeChanged( true );
|
||||
|
||||
addMouseListener( handler );
|
||||
addMouseMotionListener( handler );
|
||||
|
||||
// necessary for closing window with double-click on icon
|
||||
iconLabel.addMouseListener( handler );
|
||||
mouseLayer = new JPanel();
|
||||
mouseLayer.setOpaque( false );
|
||||
mouseLayer.addMouseListener( handler );
|
||||
mouseLayer.addMouseMotionListener( handler );
|
||||
|
||||
applyComponentOrientation( rootPane.getComponentOrientation() );
|
||||
}
|
||||
@@ -234,6 +248,11 @@ public class FlatTitlePane
|
||||
setLayout( new BorderLayout() {
|
||||
@Override
|
||||
public void layoutContainer( Container target ) {
|
||||
if( isFullWindowContent() ) {
|
||||
super.layoutContainer( target );
|
||||
return;
|
||||
}
|
||||
|
||||
// compute available bounds
|
||||
Insets insets = target.getInsets();
|
||||
int x = insets.left;
|
||||
@@ -247,7 +266,7 @@ public class FlatTitlePane
|
||||
int titleWidth = w - leftWidth - buttonsWidth;
|
||||
int minTitleWidth = UIScale.scale( titleMinimumWidth );
|
||||
|
||||
// increase minimum width if icon is show besides the title
|
||||
// increase minimum width if icon is shown besides the title
|
||||
Icon icon = titleLabel.getIcon();
|
||||
if( icon != null ) {
|
||||
Insets iconInsets = iconLabel.getInsets();
|
||||
@@ -295,6 +314,9 @@ public class FlatTitlePane
|
||||
horizontalGlue.getWidth(), titleLabel.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
// clear hit-test cache
|
||||
lastCaptionHitTestTime = 0;
|
||||
}
|
||||
} );
|
||||
|
||||
@@ -338,6 +360,13 @@ public class FlatTitlePane
|
||||
buttonPanel.add( restoreButton );
|
||||
}
|
||||
buttonPanel.add( closeButton );
|
||||
|
||||
ComponentListener l = new ComponentAdapter() {
|
||||
@Override public void componentResized( ComponentEvent e ) { updateFullWindowContentButtonsBoundsProperty(); }
|
||||
@Override public void componentMoved( ComponentEvent e ) { updateFullWindowContentButtonsBoundsProperty(); }
|
||||
};
|
||||
buttonPanel.addComponentListener( l );
|
||||
addComponentListener( l );
|
||||
}
|
||||
|
||||
protected JButton createButton( String iconKey, String accessibleName, ActionListener action ) {
|
||||
@@ -417,7 +446,9 @@ public class FlatTitlePane
|
||||
|
||||
/** @since 3 */
|
||||
protected void updateVisibility() {
|
||||
titleLabel.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_TITLE, true ) );
|
||||
boolean isFullWindowContent = isFullWindowContent();
|
||||
leftPanel.setVisible( !isFullWindowContent );
|
||||
titleLabel.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_TITLE, true ) && !isFullWindowContent );
|
||||
closeButton.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_CLOSE, true ) );
|
||||
|
||||
if( window instanceof Frame ) {
|
||||
@@ -443,7 +474,7 @@ public class FlatTitlePane
|
||||
|
||||
// get window images
|
||||
List<Image> images = null;
|
||||
if( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICON, defaultShowIcon ) ) {
|
||||
if( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICON, defaultShowIcon ) && !isFullWindowContent() ) {
|
||||
images = window.getIconImages();
|
||||
if( images.isEmpty() ) {
|
||||
// search in owners
|
||||
@@ -468,6 +499,13 @@ public class FlatTitlePane
|
||||
updateNativeTitleBarHeightAndHitTestSpotsLater();
|
||||
}
|
||||
|
||||
void updateFullWindowContentButtonsBoundsProperty() {
|
||||
Rectangle bounds = isFullWindowContent()
|
||||
? new Rectangle( SwingUtilities.convertPoint( buttonPanel, 0, 0, rootPane ), buttonPanel.getSize() )
|
||||
: null;
|
||||
rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, bounds );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
@@ -522,6 +560,11 @@ public class FlatTitlePane
|
||||
window.removeComponentListener( handler );
|
||||
}
|
||||
|
||||
/** @since 3.4 */
|
||||
protected boolean isFullWindowContent() {
|
||||
return FlatRootPaneUI.isFullWindowContent( rootPane );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this title pane currently has a visible and embedded menubar.
|
||||
*/
|
||||
@@ -533,6 +576,9 @@ public class FlatTitlePane
|
||||
* Returns whether the menubar should be embedded into the title pane.
|
||||
*/
|
||||
protected boolean isMenuBarEmbedded() {
|
||||
if( isFullWindowContent() )
|
||||
return false;
|
||||
|
||||
// not storing value of "TitlePane.menuBarEmbedded" in class to allow changing at runtime
|
||||
return FlatUIUtils.getBoolean( rootPane,
|
||||
FlatSystemProperties.MENUBAR_EMBEDDED,
|
||||
@@ -620,21 +666,45 @@ public class FlatTitlePane
|
||||
return;
|
||||
|
||||
if( debugTitleBarHeight > 0 ) {
|
||||
// title bar height is measured from window top edge
|
||||
int y = SwingUtilities.convertPoint( window, 0, debugTitleBarHeight, this ).y;
|
||||
g.setColor( Color.green );
|
||||
g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight );
|
||||
g.drawLine( 0, y, getWidth(), y );
|
||||
}
|
||||
if( debugHitTestSpots != null ) {
|
||||
for( Rectangle r : debugHitTestSpots )
|
||||
paintRect( g, Color.red, r );
|
||||
}
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
paintRect( g, Color.blue, debugAppIconBounds );
|
||||
paintRect( g, Color.blue, debugMinimizeButtonBounds );
|
||||
paintRect( g, Color.magenta, debugMaximizeButtonBounds );
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
|
||||
g.setColor( Color.red );
|
||||
debugPaintComponentWithMouseListener( g, Color.red, rootPane.getLayeredPane(), 0, 0 );
|
||||
|
||||
debugPaintRect( g, Color.blue, debugAppIconBounds );
|
||||
debugPaintRect( g, Color.blue, debugMinimizeButtonBounds );
|
||||
debugPaintRect( g, Color.magenta, debugMaximizeButtonBounds );
|
||||
debugPaintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
}
|
||||
|
||||
private void paintRect( Graphics g, Color color, Rectangle r ) {
|
||||
private void debugPaintComponentWithMouseListener( Graphics g, Color color, Component c, int x, int y ) {
|
||||
if( !c.isDisplayable() || !c.isVisible() || c == mouseLayer ||
|
||||
c == iconifyButton || c == maximizeButton || c == restoreButton || c == closeButton )
|
||||
return;
|
||||
|
||||
if( c.getMouseListeners().length > 0 ||
|
||||
c.getMouseMotionListeners().length > 0 ||
|
||||
c.getMouseWheelListeners().length > 0 )
|
||||
{
|
||||
g.drawRect( x, y, c.getWidth(), c.getHeight() );
|
||||
return;
|
||||
}
|
||||
|
||||
if( c instanceof Container ) {
|
||||
Rectangle titlePaneBoundsOnWindow = SwingUtilities.convertRectangle( this, new Rectangle( getSize() ), window );
|
||||
for( Component child : ((Container)c).getComponents() ) {
|
||||
Rectangle compBoundsOnWindow = SwingUtilities.convertRectangle( c, new Rectangle( c.getSize() ), window );
|
||||
if( compBoundsOnWindow.intersects( titlePaneBoundsOnWindow ) )
|
||||
debugPaintComponentWithMouseListener( g, color, child, x + child.getX(), y + child.getY() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void debugPaintRect( Graphics g, Color color, Rectangle r ) {
|
||||
if( r == null )
|
||||
return;
|
||||
|
||||
@@ -645,6 +715,9 @@ public class FlatTitlePane
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
if( isFullWindowContent() )
|
||||
return;
|
||||
|
||||
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
|
||||
g.setColor( (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
|
||||
@@ -866,11 +939,14 @@ public class FlatTitlePane
|
||||
return;
|
||||
|
||||
int titleBarHeight = getHeight();
|
||||
// title bar height must be measured from window top edge
|
||||
// (when window is maximized, window y location is e.g. -11 and window top inset is 11)
|
||||
for( Component c = this; c != window && c != null; c = c.getParent() )
|
||||
titleBarHeight += c.getY();
|
||||
// slightly reduce height so that component receives mouseExit events
|
||||
if( titleBarHeight > 0 )
|
||||
titleBarHeight--;
|
||||
|
||||
List<Rectangle> hitTestSpots = new ArrayList<>();
|
||||
Rectangle appIconBounds = null;
|
||||
|
||||
if( !showIconBesideTitle && iconLabel.isVisible() ) {
|
||||
@@ -928,71 +1004,17 @@ public class FlatTitlePane
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle r = getNativeHitTestSpot( buttonPanel );
|
||||
if( r != null )
|
||||
hitTestSpots.add( r );
|
||||
|
||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
|
||||
r = getNativeHitTestSpot( menuBar );
|
||||
if( r != null ) {
|
||||
// if frame is resizable and not maximized, make menu bar hit test spot smaller at top
|
||||
// to have a small area above the menu bar to resize the window
|
||||
if( window instanceof Frame && ((Frame)window).isResizable() && !isWindowMaximized() ) {
|
||||
// limit to 8, because Windows does not use a larger height
|
||||
int resizeHeight = UIScale.scale( Math.min( menuBarResizeHeight, 8 ) );
|
||||
r.y += resizeHeight;
|
||||
r.height -= resizeHeight;
|
||||
}
|
||||
|
||||
int count = menuBar.getComponentCount();
|
||||
for( int i = count - 1; i >= 0; i-- ) {
|
||||
Component c = menuBar.getComponent( i );
|
||||
if( c instanceof Box.Filler ||
|
||||
(c instanceof JComponent && clientPropertyBoolean( (JComponent) c, COMPONENT_TITLE_BAR_CAPTION, false ) ) )
|
||||
{
|
||||
// If menu bar is embedded and contains a horizontal glue or caption component,
|
||||
// then split the hit test spot so that
|
||||
// the glue/caption component area can be used to move the window.
|
||||
|
||||
Point glueLocation = SwingUtilities.convertPoint( c, 0, 0, window );
|
||||
int x2 = glueLocation.x + c.getWidth();
|
||||
Rectangle r2;
|
||||
if( getComponentOrientation().isLeftToRight() ) {
|
||||
r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height );
|
||||
|
||||
r.width = glueLocation.x - r.x;
|
||||
} else {
|
||||
r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height );
|
||||
|
||||
r.width = (r.x + r.width) - x2;
|
||||
r.x = x2;
|
||||
}
|
||||
if( r2.width > 0 )
|
||||
hitTestSpots.add( r2 );
|
||||
}
|
||||
}
|
||||
|
||||
hitTestSpots.add( r );
|
||||
}
|
||||
}
|
||||
|
||||
// allow internal frames in layered pane to be moved/resized when placed over title bar
|
||||
for( Component c : rootPane.getLayeredPane().getComponents() ) {
|
||||
r = (c instanceof JInternalFrame) ? getNativeHitTestSpot( (JInternalFrame) c ) : null;
|
||||
if( r != null )
|
||||
hitTestSpots.add( r );
|
||||
}
|
||||
|
||||
Rectangle minimizeButtonBounds = boundsInWindow( iconifyButton );
|
||||
Rectangle maximizeButtonBounds = boundsInWindow( maximizeButton.isVisible() ? maximizeButton : restoreButton );
|
||||
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
||||
|
||||
// clear hit-test cache
|
||||
lastCaptionHitTestTime = 0;
|
||||
|
||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
||||
hitTestSpots, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
this::captionHitTest, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
|
||||
debugTitleBarHeight = titleBarHeight;
|
||||
debugHitTestSpots = hitTestSpots;
|
||||
debugAppIconBounds = appIconBounds;
|
||||
debugMinimizeButtonBounds = minimizeButtonBounds;
|
||||
debugMaximizeButtonBounds = maximizeButtonBounds;
|
||||
@@ -1007,18 +1029,101 @@ public class FlatTitlePane
|
||||
: null;
|
||||
}
|
||||
|
||||
protected Rectangle getNativeHitTestSpot( JComponent c ) {
|
||||
Dimension size = c.getSize();
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
return null;
|
||||
/**
|
||||
* Returns whether there is a component at the given location, that processes
|
||||
* mouse events. E.g. buttons, menus, etc.
|
||||
* <p>
|
||||
* Note:
|
||||
* <ul>
|
||||
* <li>This method is invoked often when mouse is moved over title bar
|
||||
* and should therefore return quickly.
|
||||
* <li>This method is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
|
||||
* while processing Windows messages.
|
||||
* </ul>
|
||||
*/
|
||||
private boolean captionHitTest( Point pt ) {
|
||||
// Windows invokes this method every ~200ms, even if the mouse has not moved
|
||||
long time = System.currentTimeMillis();
|
||||
if( pt.x == lastCaptionHitTestX && pt.y == lastCaptionHitTestY && time < lastCaptionHitTestTime + 300 ) {
|
||||
lastCaptionHitTestTime = time;
|
||||
return lastCaptionHitTestResult;
|
||||
}
|
||||
|
||||
Point location = SwingUtilities.convertPoint( c, 0, 0, window );
|
||||
Rectangle r = new Rectangle( location, size );
|
||||
return r;
|
||||
// convert pt from window coordinates to layeredPane coordinates
|
||||
Component layeredPane = rootPane.getLayeredPane();
|
||||
int x = pt.x;
|
||||
int y = pt.y;
|
||||
for( Component c = layeredPane; c != window && c != null; c = c.getParent() ) {
|
||||
x -= c.getX();
|
||||
y -= c.getY();
|
||||
}
|
||||
|
||||
lastCaptionHitTestX = pt.x;
|
||||
lastCaptionHitTestY = pt.y;
|
||||
lastCaptionHitTestTime = time;
|
||||
lastCaptionHitTestResult = isTitleBarCaptionAt( layeredPane, x, y );
|
||||
return lastCaptionHitTestResult;
|
||||
}
|
||||
|
||||
private boolean isTitleBarCaptionAt( Component c, int x, int y ) {
|
||||
if( !c.isDisplayable() || !c.isVisible() || !c.contains( x, y ) || c == mouseLayer )
|
||||
return true; // continue checking with next component
|
||||
|
||||
if( c.isEnabled() &&
|
||||
(c.getMouseListeners().length > 0 ||
|
||||
c.getMouseMotionListeners().length > 0) )
|
||||
{
|
||||
if( !(c instanceof JComponent) )
|
||||
return false; // assume that this is not a caption because the component has mouse listeners
|
||||
|
||||
// check client property boolean value
|
||||
Object caption = ((JComponent)c).getClientProperty( COMPONENT_TITLE_BAR_CAPTION );
|
||||
if( caption instanceof Boolean )
|
||||
return (boolean) caption;
|
||||
|
||||
// if component is not fully layouted, do not invoke function
|
||||
// because it is too dangerous that the function tries to layout the component,
|
||||
// which could cause a dead lock
|
||||
if( !c.isValid() )
|
||||
return false; // assume that this is not a caption because the component has mouse listeners
|
||||
|
||||
if( caption instanceof Function ) {
|
||||
// check client property function value
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Function<Point, Boolean> hitTest = (Function<Point, Boolean>) caption;
|
||||
Boolean result = hitTest.apply( new Point( x, y ) );
|
||||
if( result != null )
|
||||
return result;
|
||||
} else {
|
||||
// check component UI
|
||||
ComponentUI ui = JavaCompatibility2.getUI( (JComponent) c );
|
||||
if( !(ui instanceof TitleBarCaptionHitTest) )
|
||||
return false; // assume that this is not a caption because the component has mouse listeners
|
||||
|
||||
Boolean result = ((TitleBarCaptionHitTest)ui).isTitleBarCaptionAt( x, y );
|
||||
if( result != null )
|
||||
return result;
|
||||
}
|
||||
|
||||
// else continue checking children
|
||||
}
|
||||
|
||||
// check children
|
||||
if( c instanceof Container ) {
|
||||
for( Component child : ((Container)c).getComponents() ) {
|
||||
if( !isTitleBarCaptionAt( child, x - child.getX(), y - child.getY() ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int lastCaptionHitTestX;
|
||||
private int lastCaptionHitTestY;
|
||||
private long lastCaptionHitTestTime;
|
||||
private boolean lastCaptionHitTestResult;
|
||||
|
||||
private int debugTitleBarHeight;
|
||||
private List<Rectangle> debugHitTestSpots;
|
||||
private Rectangle debugAppIconBounds;
|
||||
private Rectangle debugMinimizeButtonBounds;
|
||||
private Rectangle debugMaximizeButtonBounds;
|
||||
@@ -1116,7 +1221,7 @@ public class FlatTitlePane
|
||||
}
|
||||
}
|
||||
|
||||
// compute icon width and gap (if icon is show besides the title)
|
||||
// compute icon width and gap (if icon is shown besides the title)
|
||||
int iconTextGap = 0;
|
||||
int iconWidthAndGap = 0;
|
||||
if( icon != null ) {
|
||||
@@ -1125,7 +1230,7 @@ public class FlatTitlePane
|
||||
iconWidthAndGap = icon.getIconWidth() + iconTextGap;
|
||||
}
|
||||
|
||||
// layout title and icon (if show besides the title)
|
||||
// layout title and icon (if shown besides the title)
|
||||
String clippedText = SwingUtilities.layoutCompoundLabel( label, fontMetrics, text, icon,
|
||||
label.getVerticalAlignment(), label.getHorizontalAlignment(),
|
||||
label.getVerticalTextPosition(), label.getHorizontalTextPosition(),
|
||||
@@ -1275,7 +1380,7 @@ debug*/
|
||||
}
|
||||
|
||||
if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) {
|
||||
if( e.getSource() == iconLabel ) {
|
||||
if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) {
|
||||
// double-click on icon closes window
|
||||
close();
|
||||
} else if( !hasNativeCustomDecoration() ) {
|
||||
@@ -1302,7 +1407,7 @@ debug*/
|
||||
if( !SwingUtilities.isLeftMouseButton( e ) )
|
||||
return;
|
||||
|
||||
dragOffset = SwingUtilities.convertPoint( FlatTitlePane.this, e.getPoint(), window );
|
||||
dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window );
|
||||
linuxNativeMove = false;
|
||||
|
||||
// on Linux, move or maximize/restore window
|
||||
@@ -1415,4 +1520,27 @@ debug*/
|
||||
@Override public void componentMoved( ComponentEvent e ) {}
|
||||
@Override public void componentHidden( ComponentEvent e ) {}
|
||||
}
|
||||
|
||||
//---- interface TitleBarCaptionHitTest -----------------------------------
|
||||
|
||||
/**
|
||||
* For custom components use {@link FlatClientProperties#COMPONENT_TITLE_BAR_CAPTION}
|
||||
* instead of this interface.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public interface TitleBarCaptionHitTest {
|
||||
/**
|
||||
* Invoked for a component that is enabled and has mouse listeners,
|
||||
* to check whether it processes mouse input at the given x/y location.
|
||||
* Useful for components that do not use mouse input on whole component bounds.
|
||||
* E.g. a tabbed pane with a few tabs has some empty space beside the tabs
|
||||
* that can be used to move the window.
|
||||
*
|
||||
* @return {@code true} if the component is not interested in mouse input at the given location
|
||||
* {@code false} if the component wants process mouse input at the given location
|
||||
* {@code null} if the component children should be checked
|
||||
*/
|
||||
Boolean isTitleBarCaptionAt( int x, int y );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatToolBarUI
|
||||
extends BasicToolBarUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||
{
|
||||
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
||||
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
||||
@@ -453,6 +453,15 @@ public class FlatToolBarUI
|
||||
: null;
|
||||
}
|
||||
|
||||
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||
|
||||
/** @since 3.4 */
|
||||
@Override
|
||||
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||
// necessary because BasicToolBarUI adds some mouse listeners for dragging when toolbar is floatable
|
||||
return null; // check children
|
||||
}
|
||||
|
||||
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Action;
|
||||
|
||||
/**
|
||||
* Base class for UI actions used in ActionMap.
|
||||
* (similar to class sun.swing.UIAction)
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 3.4
|
||||
*/
|
||||
public abstract class FlatUIAction
|
||||
implements Action
|
||||
{
|
||||
protected final String name;
|
||||
protected final Action delegate;
|
||||
|
||||
protected FlatUIAction( String name ) {
|
||||
this.name = name;
|
||||
this.delegate = null;
|
||||
}
|
||||
|
||||
protected FlatUIAction( Action delegate ) {
|
||||
this.name = null;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue( String key ) {
|
||||
if( key == NAME && delegate == null )
|
||||
return name;
|
||||
return (delegate != null) ? delegate.getValue( key ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return (delegate != null) ? delegate.isEnabled() : true;
|
||||
}
|
||||
|
||||
// do nothing in following methods because this class is immutable
|
||||
@Override public void putValue( String key, Object value ) {}
|
||||
@Override public void setEnabled( boolean b ) {}
|
||||
@Override public void addPropertyChangeListener( PropertyChangeListener listener ) {}
|
||||
@Override public void removePropertyChangeListener( PropertyChangeListener listener ) {}
|
||||
}
|
||||
@@ -60,6 +60,7 @@ import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.tree.DefaultTreeCellEditor;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
@@ -304,6 +305,10 @@ public class FlatUIUtils
|
||||
if( parent instanceof JTable && ((JTable)parent).getEditorComponent() == c )
|
||||
return true;
|
||||
|
||||
// check whether used as tree cell editor
|
||||
if( parent instanceof DefaultTreeCellEditor.EditorContainer )
|
||||
return true;
|
||||
|
||||
// check whether used as cell editor
|
||||
// Table.editor is set in JTable.GenericEditor constructor
|
||||
// Tree.cellEditor is set in sun.swing.FilePane.editFileName()
|
||||
|
||||
@@ -29,8 +29,8 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.Timer;
|
||||
@@ -159,7 +159,7 @@ class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds )
|
||||
{
|
||||
@@ -168,7 +168,7 @@ class FlatWindowsNativeWindowBorder
|
||||
return;
|
||||
|
||||
wndProc.titleBarHeight = titleBarHeight;
|
||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||
wndProc.captionHitTestCallback = captionHitTestCallback;
|
||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||
@@ -288,8 +288,8 @@ class FlatWindowsNativeWindowBorder
|
||||
private final long hwnd;
|
||||
|
||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||
private int titleBarHeight;
|
||||
private Rectangle[] hitTestSpots;
|
||||
private int titleBarHeight; // measured from window top edge, which may be out-of-screen if maximized
|
||||
private Predicate<Point> captionHitTestCallback;
|
||||
private Rectangle appIconBounds;
|
||||
private Rectangle minimizeButtonBounds;
|
||||
private Rectangle maximizeButtonBounds;
|
||||
@@ -340,50 +340,61 @@ class FlatWindowsNativeWindowBorder
|
||||
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) {
|
||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||
Point pt = scaleDown( x, y );
|
||||
int sx = pt.x;
|
||||
int sy = pt.y;
|
||||
|
||||
// return HTSYSMENU if mouse is over application icon
|
||||
// - left-click on HTSYSMENU area shows system menu
|
||||
// - double-left-click sends WM_CLOSE
|
||||
if( contains( appIconBounds, sx, sy ) )
|
||||
if( contains( appIconBounds, pt ) )
|
||||
return HTSYSMENU;
|
||||
|
||||
// return HTMINBUTTON if mouse is over minimize button
|
||||
// - hovering mouse over HTMINBUTTON area shows tooltip on Windows 10/11
|
||||
if( contains( minimizeButtonBounds, sx, sy ) )
|
||||
if( contains( minimizeButtonBounds, pt ) )
|
||||
return HTMINBUTTON;
|
||||
|
||||
// return HTMAXBUTTON if mouse is over maximize/restore button
|
||||
// - hovering mouse over HTMAXBUTTON area shows tooltip on Windows 10
|
||||
// - hovering mouse over HTMAXBUTTON area shows snap layouts menu on Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
if( contains( maximizeButtonBounds, sx, sy ) )
|
||||
if( contains( maximizeButtonBounds, pt ) )
|
||||
return HTMAXBUTTON;
|
||||
|
||||
// return HTCLOSE if mouse is over close button
|
||||
// - hovering mouse over HTCLOSE area shows tooltip on Windows 10/11
|
||||
if( contains( closeButtonBounds, sx, sy ) )
|
||||
if( contains( closeButtonBounds, pt ) )
|
||||
return HTCLOSE;
|
||||
|
||||
boolean isOnTitleBar = (sy < titleBarHeight);
|
||||
// return HTTOP if mouse is over top resize border
|
||||
// - hovering mouse shows vertical resize cursor
|
||||
// - left-click and drag vertically resizes window
|
||||
if( isOnResizeBorder )
|
||||
return HTTOP;
|
||||
|
||||
boolean isOnTitleBar = (pt.y < titleBarHeight);
|
||||
if( isOnTitleBar ) {
|
||||
// use a second reference to the array to avoid that it can be changed
|
||||
// in another thread while processing the array
|
||||
Rectangle[] hitTestSpots2 = hitTestSpots;
|
||||
for( Rectangle spot : hitTestSpots2 ) {
|
||||
if( spot.contains( sx, sy ) )
|
||||
// return HTCLIENT if mouse is over any Swing component in title bar
|
||||
// that processes mouse events (e.g. buttons, menus, etc)
|
||||
// - Windows ignores mouse events in this area
|
||||
try {
|
||||
if( captionHitTestCallback != null && !captionHitTestCallback.test( pt ) )
|
||||
return HTCLIENT;
|
||||
} catch( Throwable ex ) {
|
||||
// ignore
|
||||
}
|
||||
return isOnResizeBorder ? HTTOP : HTCAPTION;
|
||||
|
||||
// return HTCAPTION if mouse is over title bar
|
||||
// - right-click shows system menu
|
||||
// - double-left-click maximizes/restores window size
|
||||
return HTCAPTION;
|
||||
}
|
||||
|
||||
return isOnResizeBorder ? HTTOP : HTCLIENT;
|
||||
// return HTCLIENT
|
||||
// - Windows ignores mouse events in this area
|
||||
return HTCLIENT;
|
||||
}
|
||||
|
||||
private boolean contains( Rectangle rect, int x, int y ) {
|
||||
return (rect != null && rect.contains( x, y ) );
|
||||
private boolean contains( Rectangle rect, Point pt ) {
|
||||
return (rect != null && rect.contains( pt ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2024 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class FullWindowContentSupport
|
||||
{
|
||||
private static final String KEY_DEBUG_SHOW_PLACEHOLDERS = "FlatLaf.debug.panel.showPlaceholders";
|
||||
|
||||
private static ArrayList<WeakReference<JComponent>> placeholders = new ArrayList<>();
|
||||
|
||||
static Dimension getPlaceholderPreferredSize( JComponent c, String options ) {
|
||||
JRootPane rootPane;
|
||||
Rectangle bounds;
|
||||
|
||||
if( !options.startsWith( SystemInfo.isMacOS ? "mac" : "win" ) ||
|
||||
!c.isDisplayable() ||
|
||||
(rootPane = SwingUtilities.getRootPane( c )) == null ||
|
||||
(bounds = (Rectangle) rootPane.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS )) == null )
|
||||
return new Dimension( 0, 0 );
|
||||
|
||||
if( options.length() > 3 ) {
|
||||
if( (options.contains( "leftToRight" ) && !c.getComponentOrientation().isLeftToRight()) ||
|
||||
(options.contains( "rightToLeft" ) && c.getComponentOrientation().isLeftToRight()) )
|
||||
return new Dimension( 0, 0 );
|
||||
}
|
||||
|
||||
// On macOS, the client property is updated very late when toggling full screen,
|
||||
// which results in "jumping" layout after full screen toggle finished.
|
||||
// To avoid that, get up-to-date buttons bounds from macOS.
|
||||
if( SystemInfo.isMacFullWindowContentSupported && FlatNativeMacLibrary.isLoaded() ) {
|
||||
Rectangle r = FlatNativeMacLibrary.getWindowButtonsBounds( SwingUtilities.windowForComponent( c ) );
|
||||
if( r != null )
|
||||
bounds = r;
|
||||
}
|
||||
|
||||
int width = bounds.width;
|
||||
int height = bounds.height;
|
||||
|
||||
if( options.length() > 3 ) {
|
||||
if( width == 0 && options.contains( "zeroInFullScreen" ) )
|
||||
height = 0;
|
||||
|
||||
if( options.contains( "horizontal" ) )
|
||||
height = 0;
|
||||
if( options.contains( "vertical" ) )
|
||||
width = 0;
|
||||
}
|
||||
|
||||
return new Dimension( width, height );
|
||||
}
|
||||
|
||||
static void registerPlaceholder( JComponent c ) {
|
||||
synchronized( placeholders ) {
|
||||
if( indexOfPlaceholder( c ) < 0 )
|
||||
placeholders.add( new WeakReference<>( c ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void unregisterPlaceholder( JComponent c ) {
|
||||
synchronized( placeholders ) {
|
||||
int index = indexOfPlaceholder( c );
|
||||
if( index >= 0 )
|
||||
placeholders.remove( index );
|
||||
}
|
||||
}
|
||||
|
||||
private static int indexOfPlaceholder( JComponent c ) {
|
||||
int size = placeholders.size();
|
||||
for( int i = 0; i < size; i++ ) {
|
||||
if( placeholders.get( i ).get() == c )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void revalidatePlaceholders( Component container ) {
|
||||
synchronized( placeholders ) {
|
||||
if( placeholders.isEmpty() )
|
||||
return;
|
||||
|
||||
for( Iterator<WeakReference<JComponent>> it = placeholders.iterator(); it.hasNext(); ) {
|
||||
WeakReference<JComponent> ref = it.next();
|
||||
JComponent c = ref.get();
|
||||
|
||||
// remove already released placeholder
|
||||
if( c == null ) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// revalidate placeholder if is in given container
|
||||
if( SwingUtilities.isDescendingFrom( c, container ) )
|
||||
c.revalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ComponentListener macInstallListeners( JRootPane rootPane ) {
|
||||
ComponentListener l = new ComponentAdapter() {
|
||||
boolean lastFullScreen;
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
Window window = SwingUtilities.windowForComponent( rootPane );
|
||||
if( window == null )
|
||||
return;
|
||||
|
||||
boolean fullScreen = FlatNativeMacLibrary.isLoaded() && FlatNativeMacLibrary.isWindowFullScreen( window );
|
||||
if( fullScreen == lastFullScreen )
|
||||
return;
|
||||
|
||||
lastFullScreen = fullScreen;
|
||||
macUpdateFullWindowContentButtonsBoundsProperty( rootPane );
|
||||
}
|
||||
};
|
||||
|
||||
rootPane.addComponentListener( l );
|
||||
return l;
|
||||
}
|
||||
|
||||
static void macUninstallListeners( JRootPane rootPane, ComponentListener l ) {
|
||||
if( l != null )
|
||||
rootPane.removeComponentListener( l );
|
||||
}
|
||||
|
||||
static void macUpdateFullWindowContentButtonsBoundsProperty( JRootPane rootPane ) {
|
||||
if( !SystemInfo.isMacFullWindowContentSupported || !rootPane.isDisplayable() )
|
||||
return;
|
||||
|
||||
Rectangle bounds = null;
|
||||
if( FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.fullWindowContent", false ) ) {
|
||||
bounds = FlatNativeMacLibrary.isLoaded()
|
||||
? FlatNativeMacLibrary.getWindowButtonsBounds( SwingUtilities.windowForComponent( rootPane ) )
|
||||
: new Rectangle( 68, 28 ); // default size
|
||||
}
|
||||
rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, bounds );
|
||||
}
|
||||
|
||||
static void macUninstallFullWindowContentButtonsBoundsProperty( JRootPane rootPane ) {
|
||||
if( !SystemInfo.isMacFullWindowContentSupported )
|
||||
return;
|
||||
|
||||
rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, null );
|
||||
}
|
||||
|
||||
static void debugPaint( Graphics g, JComponent c ) {
|
||||
if( !UIManager.getBoolean( KEY_DEBUG_SHOW_PLACEHOLDERS ) )
|
||||
return;
|
||||
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
if( width <= 0 || height <= 0 )
|
||||
return;
|
||||
|
||||
// draw red figure
|
||||
g.setColor( Color.red );
|
||||
debugPaintRect( g, new Rectangle( width, height ) );
|
||||
|
||||
// draw magenta figure if buttons bounds are not equal to placeholder bounds
|
||||
JRootPane rootPane;
|
||||
Rectangle bounds;
|
||||
if( (rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||
(bounds = (Rectangle) rootPane.getClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS )) != null &&
|
||||
(bounds.width != width || bounds.height != height) )
|
||||
{
|
||||
g.setColor( Color.magenta );
|
||||
debugPaintRect( g, SwingUtilities.convertRectangle( rootPane, bounds, c ) );
|
||||
}
|
||||
}
|
||||
|
||||
private static void debugPaintRect( Graphics g, Rectangle r ) {
|
||||
// draw rectangle
|
||||
g.drawRect( r.x, r.y, r.width - 1, r.height - 1 );
|
||||
|
||||
// draw diagonal cross
|
||||
int x2 = r.x + r.width - 1;
|
||||
int y2 = r.y + r.height - 1;
|
||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||
g.drawLine( r.x, r.y, x2, y2 );
|
||||
g.drawLine( r.x, y2, x2, r.y );
|
||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
@@ -25,6 +26,7 @@ import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
@@ -88,4 +90,64 @@ public class JavaCompatibility2
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Java 8 - 11 on Windows: sun.awt.shell.ShellFolder.get( "fileChooserShortcutPanelFolders" )
|
||||
* <br>
|
||||
* Java 12: javax.swing.filechooser.FileSystemView.getChooserShortcutPanelFiles()
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static File[] getChooserShortcutPanelFiles( FileSystemView fsv ) {
|
||||
try {
|
||||
if( SystemInfo.isJava_12_orLater ) {
|
||||
Method m = fsv.getClass().getMethod( "getChooserShortcutPanelFiles" );
|
||||
File[] files = (File[]) m.invoke( fsv );
|
||||
|
||||
// on macOS and Linux, files consists only of the user home directory
|
||||
if( files.length == 1 && files[0].equals( new File( System.getProperty( "user.home" ) ) ) )
|
||||
files = new File[0];
|
||||
|
||||
return files;
|
||||
} else if( SystemInfo.isWindows ) {
|
||||
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||
Method m = cls.getMethod( "get", String.class );
|
||||
return (File[]) m.invoke( null, "fileChooserShortcutPanelFolders" );
|
||||
}
|
||||
} catch( IllegalAccessException ex ) {
|
||||
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Java 8: sun.awt.shell.ShellFolder.get( "fileChooserComboBoxFolders" )
|
||||
* <br>
|
||||
* Java 9: javax.swing.filechooser.FileSystemView.getChooserComboBoxFiles()
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static File[] getChooserComboBoxFiles( FileSystemView fsv ) {
|
||||
try {
|
||||
if( SystemInfo.isJava_9_orLater ) {
|
||||
Method m = fsv.getClass().getMethod( "getChooserComboBoxFiles" );
|
||||
return (File[]) m.invoke( fsv );
|
||||
} else {
|
||||
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||
Method m = cls.getMethod( "get", String.class );
|
||||
return (File[]) m.invoke( null, "fileChooserComboBoxFolders" );
|
||||
}
|
||||
} catch( IllegalAccessException ex ) {
|
||||
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
|
||||
// fallback
|
||||
return new File[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -739,6 +739,8 @@ Table.rowHeight = 20
|
||||
Table.showHorizontalLines = false
|
||||
Table.showVerticalLines = false
|
||||
Table.showTrailingVerticalLine = false
|
||||
Table.paintOutsideAlternateRows = false
|
||||
Table.editorSelectAllOnStartEditing = true
|
||||
Table.consistentHomeEndKeyBehavior = true
|
||||
Table.intercellSpacing = 0,0
|
||||
Table.scrollPaneBorder = com.formdev.flatlaf.ui.FlatScrollPaneBorder
|
||||
@@ -829,7 +831,6 @@ TitlePane.centerTitleIfMenuBarEmbedded = true
|
||||
TitlePane.showIconBesideTitle = false
|
||||
TitlePane.menuBarTitleGap = 40
|
||||
TitlePane.menuBarTitleMinimumGap = 12
|
||||
TitlePane.menuBarResizeHeight = 4
|
||||
TitlePane.closeIcon = com.formdev.flatlaf.icons.FlatWindowCloseIcon
|
||||
TitlePane.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon
|
||||
TitlePane.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -73,6 +73,7 @@ class DemoFrame
|
||||
initComponents();
|
||||
updateFontMenuItems();
|
||||
initAccentColors();
|
||||
initFullWindowContent();
|
||||
controlBar.initialize( this, tabbedPane );
|
||||
|
||||
setIconImages( FlatSVGUtils.createWindowIconImages( "/com/formdev/flatlaf/demo/FlatLaf.svg" ) );
|
||||
@@ -89,24 +90,23 @@ class DemoFrame
|
||||
// do not use HTML text in menu items because this is not supported in macOS screen menu
|
||||
htmlMenuItem.setText( "some text" );
|
||||
|
||||
JRootPane rootPane = getRootPane();
|
||||
if( SystemInfo.isMacFullWindowContentSupported ) {
|
||||
// expand window content into window title bar and make title bar transparent
|
||||
getRootPane().putClientProperty( "apple.awt.fullWindowContent", true );
|
||||
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", true );
|
||||
rootPane.putClientProperty( "apple.awt.fullWindowContent", true );
|
||||
rootPane.putClientProperty( "apple.awt.transparentTitleBar", true );
|
||||
rootPane.putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING, FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_LARGE );
|
||||
|
||||
// hide window title
|
||||
if( SystemInfo.isJava_17_orLater )
|
||||
getRootPane().putClientProperty( "apple.awt.windowTitleVisible", false );
|
||||
rootPane.putClientProperty( "apple.awt.windowTitleVisible", false );
|
||||
else
|
||||
setTitle( null );
|
||||
|
||||
// add gap to left side of toolbar
|
||||
toolBar.add( Box.createHorizontalStrut( 70 ), 0 );
|
||||
}
|
||||
|
||||
// enable full screen mode for this window (for Java 8 - 10; not necessary for Java 11+)
|
||||
if( !SystemInfo.isJava_11_orLater )
|
||||
getRootPane().putClientProperty( "apple.awt.fullscreenable", true );
|
||||
rootPane.putClientProperty( "apple.awt.fullscreenable", true );
|
||||
}
|
||||
|
||||
// integrate into macOS screen menu
|
||||
@@ -461,9 +461,37 @@ class DemoFrame
|
||||
accentColorButtons[i].setVisible( isAccentColorSupported );
|
||||
}
|
||||
|
||||
private void initFullWindowContent() {
|
||||
if( !supportsFlatLafWindowDecorations() )
|
||||
return;
|
||||
|
||||
// create fullWindowContent mode toggle button
|
||||
Icon expandIcon = new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/expand.svg" );
|
||||
Icon collapseIcon = new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/collapse.svg" );
|
||||
JToggleButton fullWindowContentButton = new JToggleButton( expandIcon );
|
||||
fullWindowContentButton.setToolTipText( "Toggle full window content" );
|
||||
fullWindowContentButton.addActionListener( e -> {
|
||||
boolean fullWindowContent = fullWindowContentButton.isSelected();
|
||||
fullWindowContentButton.setIcon( fullWindowContent ? collapseIcon : expandIcon );
|
||||
menuBar.setVisible( !fullWindowContent );
|
||||
toolBar.setVisible( !fullWindowContent );
|
||||
getRootPane().putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT, fullWindowContent );
|
||||
} );
|
||||
|
||||
// add fullWindowContent mode toggle button to tabbed pane
|
||||
JToolBar trailingToolBar = new JToolBar();
|
||||
trailingToolBar.add( Box.createGlue() );
|
||||
trailingToolBar.add( fullWindowContentButton );
|
||||
tabbedPane.putClientProperty( FlatClientProperties.TABBED_PANE_TRAILING_COMPONENT, trailingToolBar );
|
||||
}
|
||||
|
||||
private boolean supportsFlatLafWindowDecorations() {
|
||||
return FlatLaf.supportsNativeWindowDecorations() || (SystemInfo.isLinux && JFrame.isDefaultLookAndFeelDecorated());
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JMenuBar menuBar1 = new JMenuBar();
|
||||
menuBar = new JMenuBar();
|
||||
JMenu fileMenu = new JMenu();
|
||||
JMenuItem newMenuItem = new JMenuItem();
|
||||
JMenuItem openMenuItem = new JMenuItem();
|
||||
@@ -509,6 +537,8 @@ class DemoFrame
|
||||
JMenuItem showUIDefaultsInspectorMenuItem = new JMenuItem();
|
||||
JMenu helpMenu = new JMenu();
|
||||
aboutMenuItem = new JMenuItem();
|
||||
JPanel toolBarPanel = new JPanel();
|
||||
JPanel macFullWindowContentButtonsPlaceholder = new JPanel();
|
||||
toolBar = new JToolBar();
|
||||
JButton backButton = new JButton();
|
||||
JButton forwardButton = new JButton();
|
||||
@@ -524,8 +554,10 @@ class DemoFrame
|
||||
DataComponentsPanel dataComponentsPanel = new DataComponentsPanel();
|
||||
TabsPanel tabsPanel = new TabsPanel();
|
||||
OptionPanePanel optionPanePanel = new OptionPanePanel();
|
||||
ExtrasPanel extrasPanel1 = new ExtrasPanel();
|
||||
ExtrasPanel extrasPanel = new ExtrasPanel();
|
||||
controlBar = new ControlBar();
|
||||
JPanel themesPanelPanel = new JPanel();
|
||||
JPanel winFullWindowContentButtonsPlaceholder = new JPanel();
|
||||
themesPanel = new IJThemesPanel();
|
||||
|
||||
//======== this ========
|
||||
@@ -534,7 +566,7 @@ class DemoFrame
|
||||
Container contentPane = getContentPane();
|
||||
contentPane.setLayout(new BorderLayout());
|
||||
|
||||
//======== menuBar1 ========
|
||||
//======== menuBar ========
|
||||
{
|
||||
|
||||
//======== fileMenu ========
|
||||
@@ -579,7 +611,7 @@ class DemoFrame
|
||||
exitMenuItem.addActionListener(e -> exitActionPerformed());
|
||||
fileMenu.add(exitMenuItem);
|
||||
}
|
||||
menuBar1.add(fileMenu);
|
||||
menuBar.add(fileMenu);
|
||||
|
||||
//======== editMenu ========
|
||||
{
|
||||
@@ -632,7 +664,7 @@ class DemoFrame
|
||||
deleteMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
editMenu.add(deleteMenuItem);
|
||||
}
|
||||
menuBar1.add(editMenu);
|
||||
menuBar.add(editMenu);
|
||||
|
||||
//======== viewMenu ========
|
||||
{
|
||||
@@ -732,7 +764,7 @@ class DemoFrame
|
||||
radioButtonMenuItem3.addActionListener(e -> menuItemActionPerformed(e));
|
||||
viewMenu.add(radioButtonMenuItem3);
|
||||
}
|
||||
menuBar1.add(viewMenu);
|
||||
menuBar.add(viewMenu);
|
||||
|
||||
//======== fontMenu ========
|
||||
{
|
||||
@@ -756,7 +788,7 @@ class DemoFrame
|
||||
decrFontMenuItem.addActionListener(e -> decrFont());
|
||||
fontMenu.add(decrFontMenuItem);
|
||||
}
|
||||
menuBar1.add(fontMenu);
|
||||
menuBar.add(fontMenu);
|
||||
|
||||
//======== optionsMenu ========
|
||||
{
|
||||
@@ -808,7 +840,7 @@ class DemoFrame
|
||||
showUIDefaultsInspectorMenuItem.addActionListener(e -> showUIDefaultsInspector());
|
||||
optionsMenu.add(showUIDefaultsInspectorMenuItem);
|
||||
}
|
||||
menuBar1.add(optionsMenu);
|
||||
menuBar.add(optionsMenu);
|
||||
|
||||
//======== helpMenu ========
|
||||
{
|
||||
@@ -821,54 +853,66 @@ class DemoFrame
|
||||
aboutMenuItem.addActionListener(e -> aboutActionPerformed());
|
||||
helpMenu.add(aboutMenuItem);
|
||||
}
|
||||
menuBar1.add(helpMenu);
|
||||
menuBar.add(helpMenu);
|
||||
}
|
||||
setJMenuBar(menuBar1);
|
||||
setJMenuBar(menuBar);
|
||||
|
||||
//======== toolBar ========
|
||||
//======== toolBarPanel ========
|
||||
{
|
||||
toolBar.setMargin(new Insets(3, 3, 3, 3));
|
||||
toolBarPanel.setLayout(new BorderLayout());
|
||||
|
||||
//---- backButton ----
|
||||
backButton.setToolTipText("Back");
|
||||
backButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/back.svg"));
|
||||
toolBar.add(backButton);
|
||||
//======== macFullWindowContentButtonsPlaceholder ========
|
||||
{
|
||||
macFullWindowContentButtonsPlaceholder.setLayout(new FlowLayout());
|
||||
}
|
||||
toolBarPanel.add(macFullWindowContentButtonsPlaceholder, BorderLayout.WEST);
|
||||
|
||||
//---- forwardButton ----
|
||||
forwardButton.setToolTipText("Forward");
|
||||
forwardButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/forward.svg"));
|
||||
toolBar.add(forwardButton);
|
||||
toolBar.addSeparator();
|
||||
//======== toolBar ========
|
||||
{
|
||||
toolBar.setMargin(new Insets(3, 3, 3, 3));
|
||||
|
||||
//---- cutButton ----
|
||||
cutButton.setToolTipText("Cut");
|
||||
cutButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-cut.svg"));
|
||||
toolBar.add(cutButton);
|
||||
//---- backButton ----
|
||||
backButton.setToolTipText("Back");
|
||||
backButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/back.svg"));
|
||||
toolBar.add(backButton);
|
||||
|
||||
//---- copyButton ----
|
||||
copyButton.setToolTipText("Copy");
|
||||
copyButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/copy.svg"));
|
||||
toolBar.add(copyButton);
|
||||
//---- forwardButton ----
|
||||
forwardButton.setToolTipText("Forward");
|
||||
forwardButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/forward.svg"));
|
||||
toolBar.add(forwardButton);
|
||||
toolBar.addSeparator();
|
||||
|
||||
//---- pasteButton ----
|
||||
pasteButton.setToolTipText("Paste");
|
||||
pasteButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-paste.svg"));
|
||||
toolBar.add(pasteButton);
|
||||
toolBar.addSeparator();
|
||||
//---- cutButton ----
|
||||
cutButton.setToolTipText("Cut");
|
||||
cutButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-cut.svg"));
|
||||
toolBar.add(cutButton);
|
||||
|
||||
//---- refreshButton ----
|
||||
refreshButton.setToolTipText("Refresh");
|
||||
refreshButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/refresh.svg"));
|
||||
toolBar.add(refreshButton);
|
||||
toolBar.addSeparator();
|
||||
//---- copyButton ----
|
||||
copyButton.setToolTipText("Copy");
|
||||
copyButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/copy.svg"));
|
||||
toolBar.add(copyButton);
|
||||
|
||||
//---- showToggleButton ----
|
||||
showToggleButton.setSelected(true);
|
||||
showToggleButton.setToolTipText("Show Details");
|
||||
showToggleButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/show.svg"));
|
||||
toolBar.add(showToggleButton);
|
||||
//---- pasteButton ----
|
||||
pasteButton.setToolTipText("Paste");
|
||||
pasteButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-paste.svg"));
|
||||
toolBar.add(pasteButton);
|
||||
toolBar.addSeparator();
|
||||
|
||||
//---- refreshButton ----
|
||||
refreshButton.setToolTipText("Refresh");
|
||||
refreshButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/refresh.svg"));
|
||||
toolBar.add(refreshButton);
|
||||
toolBar.addSeparator();
|
||||
|
||||
//---- showToggleButton ----
|
||||
showToggleButton.setSelected(true);
|
||||
showToggleButton.setToolTipText("Show Details");
|
||||
showToggleButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/show.svg"));
|
||||
toolBar.add(showToggleButton);
|
||||
}
|
||||
toolBarPanel.add(toolBar, BorderLayout.CENTER);
|
||||
}
|
||||
contentPane.add(toolBar, BorderLayout.NORTH);
|
||||
contentPane.add(toolBarPanel, BorderLayout.PAGE_START);
|
||||
|
||||
//======== contentPanel ========
|
||||
{
|
||||
@@ -888,13 +932,25 @@ class DemoFrame
|
||||
tabbedPane.addTab("Data Components", dataComponentsPanel);
|
||||
tabbedPane.addTab("Tabs", tabsPanel);
|
||||
tabbedPane.addTab("Option Pane", optionPanePanel);
|
||||
tabbedPane.addTab("Extras", extrasPanel1);
|
||||
tabbedPane.addTab("Extras", extrasPanel);
|
||||
}
|
||||
contentPanel.add(tabbedPane, "cell 0 0");
|
||||
}
|
||||
contentPane.add(contentPanel, BorderLayout.CENTER);
|
||||
contentPane.add(controlBar, BorderLayout.SOUTH);
|
||||
contentPane.add(themesPanel, BorderLayout.EAST);
|
||||
contentPane.add(controlBar, BorderLayout.PAGE_END);
|
||||
|
||||
//======== themesPanelPanel ========
|
||||
{
|
||||
themesPanelPanel.setLayout(new BorderLayout());
|
||||
|
||||
//======== winFullWindowContentButtonsPlaceholder ========
|
||||
{
|
||||
winFullWindowContentButtonsPlaceholder.setLayout(new FlowLayout());
|
||||
}
|
||||
themesPanelPanel.add(winFullWindowContentButtonsPlaceholder, BorderLayout.NORTH);
|
||||
themesPanelPanel.add(themesPanel, BorderLayout.CENTER);
|
||||
}
|
||||
contentPane.add(themesPanelPanel, BorderLayout.LINE_END);
|
||||
|
||||
//---- buttonGroup1 ----
|
||||
ButtonGroup buttonGroup1 = new ButtonGroup();
|
||||
@@ -909,8 +965,8 @@ class DemoFrame
|
||||
usersButton.setButtonType( ButtonType.toolBarButton );
|
||||
usersButton.setFocusable( false );
|
||||
usersButton.addActionListener( e -> JOptionPane.showMessageDialog( null, "Hello User! How are you?", "User", JOptionPane.INFORMATION_MESSAGE ) );
|
||||
menuBar1.add( Box.createGlue() );
|
||||
menuBar1.add( usersButton );
|
||||
menuBar.add( Box.createGlue() );
|
||||
menuBar.add( usersButton );
|
||||
|
||||
cutMenuItem.addActionListener( new DefaultEditorKit.CutAction() );
|
||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||
@@ -922,7 +978,7 @@ class DemoFrame
|
||||
for( int i = 1; i <= 100; i++ )
|
||||
scrollingPopupMenu.add( "Item " + i );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() || (SystemInfo.isLinux && JFrame.isDefaultLookAndFeelDecorated()) ) {
|
||||
if( supportsFlatLafWindowDecorations() ) {
|
||||
if( SystemInfo.isLinux )
|
||||
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||
else
|
||||
@@ -943,6 +999,17 @@ class DemoFrame
|
||||
if( "false".equals( System.getProperty( "flatlaf.animatedLafChange" ) ) )
|
||||
animatedLafChangeMenuItem.setSelected( false );
|
||||
|
||||
|
||||
// on macOS, panel left to toolBar is a placeholder for title bar buttons in fullWindowContent mode
|
||||
macFullWindowContentButtonsPlaceholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac zeroInFullScreen" );
|
||||
|
||||
// on Windows/Linux, panel above themesPanel is a placeholder for title bar buttons in fullWindowContent mode
|
||||
winFullWindowContentButtonsPlaceholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "win" );
|
||||
|
||||
// uncomment this line to see title bar buttons placeholders in fullWindowContent mode
|
||||
// UIManager.put( "FlatLaf.debug.panel.showPlaceholders", true );
|
||||
|
||||
|
||||
// remove contentPanel bottom insets
|
||||
MigLayout layout = (MigLayout) contentPanel.getLayout();
|
||||
LC lc = ConstraintParser.parseLayoutConstraint( (String) layout.getLayoutConstraints() );
|
||||
@@ -963,6 +1030,7 @@ class DemoFrame
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JMenuBar menuBar;
|
||||
private JMenuItem exitMenuItem;
|
||||
private JMenu scrollingPopupMenu;
|
||||
private JMenuItem htmlMenuItem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "8.2.1.0.348" Java: "21.0.1" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -12,59 +12,69 @@ new FormModel {
|
||||
"defaultCloseOperation": 2
|
||||
"$locationPolicy": 2
|
||||
"$sizePolicy": 2
|
||||
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
|
||||
name: "toolBar"
|
||||
"margin": new java.awt.Insets( 3, 3, 3, 3 )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "backButton"
|
||||
"toolTipText": "Back"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/back.svg" )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "toolBarPanel"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||
name: "macFullWindowContentButtonsPlaceholder"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "West"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "forwardButton"
|
||||
"toolTipText": "Forward"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/forward.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "cutButton"
|
||||
"toolTipText": "Cut"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-cut.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "copyButton"
|
||||
"toolTipText": "Copy"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/copy.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "pasteButton"
|
||||
"toolTipText": "Paste"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-paste.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "refreshButton"
|
||||
"toolTipText": "Refresh"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/refresh.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "showToggleButton"
|
||||
"selected": true
|
||||
"toolTipText": "Show Details"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/show.svg" )
|
||||
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
|
||||
name: "toolBar"
|
||||
"margin": new java.awt.Insets( 3, 3, 3, 3 )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "backButton"
|
||||
"toolTipText": "Back"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/back.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "forwardButton"
|
||||
"toolTipText": "Forward"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/forward.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "cutButton"
|
||||
"toolTipText": "Cut"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-cut.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "copyButton"
|
||||
"toolTipText": "Copy"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/copy.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "pasteButton"
|
||||
"toolTipText": "Paste"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-paste.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "refreshButton"
|
||||
"toolTipText": "Refresh"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/refresh.svg" )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
name: "separator7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "showToggleButton"
|
||||
"selected": true
|
||||
"toolTipText": "Show Details"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/show.svg" )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "North"
|
||||
"value": "First"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
@@ -105,7 +115,7 @@ new FormModel {
|
||||
"title": "Option Pane"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.extras.ExtrasPanel" ) {
|
||||
name: "extrasPanel1"
|
||||
name: "extrasPanel"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"title": "Extras"
|
||||
} )
|
||||
@@ -121,19 +131,32 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "South"
|
||||
"value": "Last"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel" ) {
|
||||
name: "themesPanel"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.variableModifiers": 0
|
||||
}
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "themesPanelPanel"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||
name: "winFullWindowContentButtonsPlaceholder"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "North"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel" ) {
|
||||
name: "themesPanel"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.variableModifiers": 0
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "East"
|
||||
"value": "After"
|
||||
} )
|
||||
menuBar: new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
|
||||
name: "menuBar1"
|
||||
name: "menuBar"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "fileMenu"
|
||||
"text": "File"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.5 14.5L6 10M14.5 1.5L9.99998 6.00001M2.5 9.50001H6.5L6.5 13.5M13.5 6.5L9.5 6.50003V2.5" stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 396 B |
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.5 9.5L2 14M9.50003 6.50004L14 2.00001M5.5 14.5H1.5V10.5M10.5 1.5L14.5 1.50002V5.5" stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 391 B |
@@ -56,7 +56,7 @@ tasks {
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
|
||||
withType<PublishToMavenRepository>().configureEach {
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
onlyIf { !rootProject.hasProperty( "skipFonts" ) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ tasks {
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
|
||||
withType<PublishToMavenRepository>().configureEach {
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
onlyIf { !rootProject.hasProperty( "skipFonts" ) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ tasks {
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
|
||||
withType<PublishToMavenRepository>().configureEach {
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
onlyIf { !rootProject.hasProperty( "skipFonts" ) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ tasks {
|
||||
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
|
||||
withType<PublishToMavenRepository>().configureEach {
|
||||
withType<AbstractPublishToMaven>().configureEach {
|
||||
onlyIf { !rootProject.hasProperty( "skipFonts" ) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.jideoss.ui;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.COMPONENT_TITLE_BAR_CAPTION;
|
||||
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
|
||||
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
|
||||
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean;
|
||||
@@ -30,6 +31,7 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.event.MouseListener;
|
||||
@@ -37,6 +39,7 @@ import java.awt.event.MouseMotionListener;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
@@ -100,6 +103,25 @@ public class FlatJideTabbedPaneUI
|
||||
return new FlatJideTabbedPaneUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
c.putClientProperty( COMPONENT_TITLE_BAR_CAPTION,
|
||||
(Function<Point, Boolean>) pt -> {
|
||||
if( tabForCoordinate( _tabPane, pt.x, pt.y ) >= 0 )
|
||||
return false;
|
||||
|
||||
return null; // check children
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
c.putClientProperty( COMPONENT_TITLE_BAR_CAPTION, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
@@ -32,8 +32,8 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.Timer;
|
||||
@@ -164,7 +164,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds )
|
||||
{
|
||||
@@ -173,7 +173,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
return;
|
||||
|
||||
wndProc.titleBarHeight = titleBarHeight;
|
||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||
wndProc.captionHitTestCallback = captionHitTestCallback;
|
||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||
@@ -351,7 +351,7 @@ public class FlatWindowsNativeWindowBorder
|
||||
|
||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||
private int titleBarHeight;
|
||||
private Rectangle[] hitTestSpots;
|
||||
private Predicate<Point> captionHitTestCallback;
|
||||
private Rectangle appIconBounds;
|
||||
private Rectangle minimizeButtonBounds;
|
||||
private Rectangle maximizeButtonBounds;
|
||||
@@ -644,53 +644,65 @@ public class FlatWindowsNativeWindowBorder
|
||||
|
||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||
Point pt = scaleDown( x, y );
|
||||
int sx = pt.x;
|
||||
int sy = pt.y;
|
||||
|
||||
// return HTSYSMENU if mouse is over application icon
|
||||
// - left-click on HTSYSMENU area shows system menu
|
||||
// - double-left-click sends WM_CLOSE
|
||||
if( contains( appIconBounds, sx, sy ) )
|
||||
if( contains( appIconBounds, pt ) )
|
||||
return new LRESULT( HTSYSMENU );
|
||||
|
||||
// return HTMINBUTTON if mouse is over minimize button
|
||||
// - hovering mouse over HTMINBUTTON area shows tooltip on Windows 10/11
|
||||
if( contains( minimizeButtonBounds, sx, sy ) )
|
||||
if( contains( minimizeButtonBounds, pt ) )
|
||||
return new LRESULT( HTMINBUTTON );
|
||||
|
||||
// return HTMAXBUTTON if mouse is over maximize/restore button
|
||||
// - hovering mouse over HTMAXBUTTON area shows tooltip on Windows 10
|
||||
// - hovering mouse over HTMAXBUTTON area shows snap layouts menu on Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
if( contains( maximizeButtonBounds, sx, sy ) )
|
||||
if( contains( maximizeButtonBounds, pt ) )
|
||||
return new LRESULT( HTMAXBUTTON );
|
||||
|
||||
// return HTCLOSE if mouse is over close button
|
||||
// - hovering mouse over HTCLOSE area shows tooltip on Windows 10/11
|
||||
if( contains( closeButtonBounds, sx, sy ) )
|
||||
if( contains( closeButtonBounds, pt ) )
|
||||
return new LRESULT( HTCLOSE );
|
||||
|
||||
int resizeBorderHeight = getResizeHandleHeight();
|
||||
boolean isOnResizeBorder = (y < resizeBorderHeight) &&
|
||||
(User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
||||
boolean isOnTitleBar = (sy < titleBarHeight);
|
||||
|
||||
// return HTTOP if mouse is over top resize border
|
||||
// - hovering mouse shows vertical resize cursor
|
||||
// - left-click and drag vertically resizes window
|
||||
if( isOnResizeBorder )
|
||||
return new LRESULT( HTTOP );
|
||||
|
||||
boolean isOnTitleBar = (pt.y < titleBarHeight);
|
||||
if( isOnTitleBar ) {
|
||||
// use a second reference to the array to avoid that it can be changed
|
||||
// in another thread while processing the array
|
||||
Rectangle[] hitTestSpots2 = hitTestSpots;
|
||||
for( Rectangle spot : hitTestSpots2 ) {
|
||||
if( spot.contains( sx, sy ) )
|
||||
// return HTCLIENT if mouse is over any Swing component in title bar
|
||||
// that processes mouse events (e.g. buttons, menus, etc)
|
||||
// - Windows ignores mouse events in this area
|
||||
try {
|
||||
if( captionHitTestCallback != null && !captionHitTestCallback.test( pt ) )
|
||||
return new LRESULT( HTCLIENT );
|
||||
} catch( Throwable ex ) {
|
||||
// ignore
|
||||
}
|
||||
return new LRESULT( isOnResizeBorder ? HTTOP : HTCAPTION );
|
||||
|
||||
// return HTCAPTION if mouse is over title bar
|
||||
// - right-click shows system menu
|
||||
// - double-left-click maximizes/restores window size
|
||||
return new LRESULT( HTCAPTION );
|
||||
}
|
||||
|
||||
return new LRESULT( isOnResizeBorder ? HTTOP : HTCLIENT );
|
||||
// return HTCLIENT
|
||||
// - Windows ignores mouse events in this area
|
||||
return new LRESULT( HTCLIENT );
|
||||
}
|
||||
|
||||
private boolean contains( Rectangle rect, int x, int y ) {
|
||||
return (rect != null && rect.contains( x, y ) );
|
||||
private boolean contains( Rectangle rect, Point pt ) {
|
||||
return (rect != null && rect.contains( pt ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,4 +41,6 @@
|
||||
}
|
||||
|
||||
|
||||
jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName, const char* fieldSignature );
|
||||
jclass findClass( JNIEnv *env, const char* className, bool globalRef );
|
||||
jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName, const char* fieldSignature, bool staticField );
|
||||
jmethodID getMethodID( JNIEnv *env, jclass cls, const char* methodName, const char* methodSignature, bool staticMethod );
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_DEFAULT
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_DEFAULT 0L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_MEDIUM
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_MEDIUM 1L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE 2L
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: setWindowRoundedBorder
|
||||
@@ -15,6 +21,38 @@ extern "C" {
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowRoundedBorder
|
||||
(JNIEnv *, jclass, jobject, jfloat, jfloat, jint);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: setWindowButtonsSpacing
|
||||
* Signature: (Ljava/awt/Window;I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowButtonsSpacing
|
||||
(JNIEnv *, jclass, jobject, jint);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: getWindowButtonsBounds
|
||||
* Signature: (Ljava/awt/Window;)Ljava/awt/Rectangle;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWindowButtonsBounds
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: isWindowFullScreen
|
||||
* Signature: (Ljava/awt/Window;)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_isWindowFullScreen
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: toggleWindowFullScreen
|
||||
* Signature: (Ljava/awt/Window;)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_toggleWindowFullScreen
|
||||
(JNIEnv *, jclass, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName, const char* fieldSignature ) {
|
||||
// NSLog( @"getFieldID %s %s %s", className, fieldName, fieldSignature );
|
||||
jclass findClass( JNIEnv *env, const char* className, bool globalRef ) {
|
||||
// NSLog( @"findClass %s", className );
|
||||
|
||||
jclass cls = env->FindClass( className );
|
||||
if( cls == NULL ) {
|
||||
@@ -32,7 +32,22 @@ jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jfieldID fieldID = env->GetFieldID( cls, fieldName, fieldSignature );
|
||||
if( globalRef )
|
||||
cls = reinterpret_cast<jclass>( env->NewGlobalRef( cls ) );
|
||||
|
||||
return cls;
|
||||
}
|
||||
|
||||
jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName, const char* fieldSignature, bool staticField ) {
|
||||
// NSLog( @"getFieldID %s %s %s", className, fieldName, fieldSignature );
|
||||
|
||||
jclass cls = findClass( env, className, false );
|
||||
if( cls == NULL )
|
||||
return NULL;
|
||||
|
||||
jfieldID fieldID = staticField
|
||||
? env->GetStaticFieldID( cls, fieldName, fieldSignature )
|
||||
: env->GetFieldID( cls, fieldName, fieldSignature );
|
||||
if( fieldID == NULL ) {
|
||||
NSLog( @"FlatLaf: failed to lookup field '%s' of type '%s' in class '%s'", fieldName, fieldSignature, className );
|
||||
env->ExceptionDescribe(); // print stack trace
|
||||
@@ -42,3 +57,22 @@ jfieldID getFieldID( JNIEnv *env, const char* className, const char* fieldName,
|
||||
|
||||
return fieldID;
|
||||
}
|
||||
|
||||
jmethodID getMethodID( JNIEnv *env, jclass cls, const char* methodName, const char* methodSignature, bool staticMethod ) {
|
||||
// NSLog( @"getMethodID %s %s", methodName, methodSignature );
|
||||
|
||||
if( cls == NULL )
|
||||
return NULL;
|
||||
|
||||
jmethodID methodID = staticMethod
|
||||
? env->GetStaticMethodID( cls, methodName, methodSignature )
|
||||
: env->GetMethodID( cls, methodName, methodSignature );
|
||||
if( methodID == NULL ) {
|
||||
NSLog( @"FlatLaf: failed to lookup method '%s' of type '%s'", methodName, methodSignature );
|
||||
env->ExceptionDescribe(); // print stack trace
|
||||
env->ExceptionClear();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return methodID;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <jni.h>
|
||||
#import "JNIUtils.h"
|
||||
#import "JNFRunLoop.h"
|
||||
@@ -24,14 +25,37 @@
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@interface WindowData : NSObject
|
||||
// used when window is full screen
|
||||
@property (nonatomic) int lastWindowButtonAreaWidth;
|
||||
@property (nonatomic) int lastWindowTitleBarHeight;
|
||||
|
||||
// full screen observers
|
||||
@property (nonatomic) id willEnterFullScreenObserver;
|
||||
@property (nonatomic) id willExitFullScreenObserver;
|
||||
@property (nonatomic) id didExitFullScreenObserver;
|
||||
@end
|
||||
|
||||
@implementation WindowData
|
||||
@end
|
||||
|
||||
// declare internal methods
|
||||
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window );
|
||||
WindowData* getWindowData( NSWindow* nsWindow, bool allocate );
|
||||
void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden );
|
||||
int getWindowButtonAreaWidth( NSWindow* nsWindow );
|
||||
int getWindowTitleBarHeight( NSWindow* nsWindow );
|
||||
bool isWindowFullScreen( NSWindow* nsWindow );
|
||||
|
||||
|
||||
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
||||
if( window == NULL )
|
||||
return NULL;
|
||||
|
||||
// initialize field IDs (done only once because fields are static)
|
||||
static jfieldID peerID = getFieldID( env, "java/awt/Component", "peer", "Ljava/awt/peer/ComponentPeer;" );
|
||||
static jfieldID platformWindowID = getFieldID( env, "sun/lwawt/LWWindowPeer", "platformWindow", "Lsun/lwawt/PlatformWindow;" );
|
||||
static jfieldID ptrID = getFieldID( env, "sun/lwawt/macosx/CFRetainedResource", "ptr", "J" );
|
||||
// initialize field IDs (done only once because variables are static)
|
||||
static jfieldID peerID = getFieldID( env, "java/awt/Component", "peer", "Ljava/awt/peer/ComponentPeer;", false );
|
||||
static jfieldID platformWindowID = getFieldID( env, "sun/lwawt/LWWindowPeer", "platformWindow", "Lsun/lwawt/PlatformWindow;", false );
|
||||
static jfieldID ptrID = getFieldID( env, "sun/lwawt/macosx/CFRetainedResource", "ptr", "J", false );
|
||||
if( peerID == NULL || platformWindowID == NULL || ptrID == NULL )
|
||||
return NULL;
|
||||
|
||||
@@ -49,6 +73,16 @@ NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
||||
return (NSWindow *) jlong_to_ptr( env->GetLongField( platformWindow, ptrID ) );
|
||||
}
|
||||
|
||||
WindowData* getWindowData( NSWindow* nsWindow, bool allocate ) {
|
||||
static char key;
|
||||
WindowData* windowData = objc_getAssociatedObject( nsWindow, &key );
|
||||
if( windowData == NULL && allocate ) {
|
||||
windowData = [WindowData new];
|
||||
objc_setAssociatedObject( nsWindow, &key, windowData, OBJC_ASSOCIATION_RETAIN_NONATOMIC );
|
||||
}
|
||||
return windowData;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowRoundedBorder
|
||||
( JNIEnv* env, jclass cls, jobject window, jfloat radius, jfloat borderWidth, jint borderColor )
|
||||
@@ -87,3 +121,259 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
||||
JNI_COCOA_EXIT()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setWindowButtonsSpacing
|
||||
( JNIEnv* env, jclass cls, jobject window, jint buttonsSpacing )
|
||||
{
|
||||
JNI_COCOA_ENTER()
|
||||
|
||||
NSWindow* nsWindow = getNSWindow( env, cls, window );
|
||||
if( nsWindow == NULL )
|
||||
return FALSE;
|
||||
|
||||
#define SPACING_DEFAULT com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_DEFAULT
|
||||
#define SPACING_MEDIUM com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_MEDIUM
|
||||
#define SPACING_LARGE com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE
|
||||
|
||||
bool isMacOS_11_orLater = @available( macOS 11, * );
|
||||
if( !isMacOS_11_orLater && buttonsSpacing == SPACING_LARGE )
|
||||
buttonsSpacing = SPACING_MEDIUM;
|
||||
int oldButtonsSpacing = (nsWindow.toolbar != NULL)
|
||||
? ((isMacOS_11_orLater && nsWindow.toolbarStyle == NSWindowToolbarStyleUnified)
|
||||
? SPACING_LARGE
|
||||
: SPACING_MEDIUM)
|
||||
: SPACING_DEFAULT;
|
||||
|
||||
if( buttonsSpacing == oldButtonsSpacing )
|
||||
return TRUE;
|
||||
|
||||
WindowData* windowData = getWindowData( nsWindow, true );
|
||||
|
||||
[FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
|
||||
// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] );
|
||||
|
||||
// add/remove toolbar
|
||||
NSToolbar* toolbar = NULL;
|
||||
bool needsToolbar = (buttonsSpacing != SPACING_DEFAULT);
|
||||
if( needsToolbar ) {
|
||||
toolbar = [NSToolbar new];
|
||||
toolbar.showsBaselineSeparator = NO; // necessary for older macOS versions
|
||||
if( isWindowFullScreen( nsWindow ) )
|
||||
toolbar.visible = NO;
|
||||
}
|
||||
nsWindow.toolbar = toolbar;
|
||||
|
||||
if( isMacOS_11_orLater ) {
|
||||
nsWindow.toolbarStyle = (buttonsSpacing == SPACING_LARGE)
|
||||
? NSWindowToolbarStyleUnified
|
||||
: (buttonsSpacing == SPACING_MEDIUM)
|
||||
? NSWindowToolbarStyleUnifiedCompact
|
||||
: NSWindowToolbarStyleAutomatic;
|
||||
}
|
||||
|
||||
windowData.lastWindowButtonAreaWidth = 0;
|
||||
windowData.lastWindowTitleBarHeight = 0;
|
||||
|
||||
// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] );
|
||||
|
||||
// when window becomes full screen, it is necessary to hide the toolbar
|
||||
// because it otherwise is shown non-transparent and hides Swing components
|
||||
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
|
||||
if( needsToolbar && windowData.willEnterFullScreenObserver == NULL ) {
|
||||
// NSLog( @"add observers %@", nsWindow );
|
||||
windowData.willEnterFullScreenObserver = [center addObserverForName:NSWindowWillEnterFullScreenNotification
|
||||
object:nsWindow queue:nil usingBlock:^(NSNotification *note) {
|
||||
// NSLog( @"enter full screen %@", nsWindow );
|
||||
if( nsWindow.toolbar != NULL ) {
|
||||
// remember button area width, which is used later when window exits full screen
|
||||
// remembar title bar height so that "main" JToolBar keeps its height in full screen
|
||||
windowData.lastWindowButtonAreaWidth = getWindowButtonAreaWidth( nsWindow );
|
||||
windowData.lastWindowTitleBarHeight = getWindowTitleBarHeight( nsWindow );
|
||||
// NSLog( @"%d %d", windowData.lastWindowButtonAreaWidth, windowData.lastWindowTitleBarHeight );
|
||||
|
||||
nsWindow.toolbar.visible = NO;
|
||||
}
|
||||
}];
|
||||
|
||||
windowData.willExitFullScreenObserver = [center addObserverForName:NSWindowWillExitFullScreenNotification
|
||||
object:nsWindow queue:nil usingBlock:^(NSNotification *note) {
|
||||
// NSLog( @"will exit full screen %@", nsWindow );
|
||||
if( nsWindow.toolbar != NULL )
|
||||
setWindowButtonsHidden( nsWindow, true );
|
||||
}];
|
||||
|
||||
windowData.didExitFullScreenObserver = [center addObserverForName:NSWindowDidExitFullScreenNotification
|
||||
object:nsWindow queue:nil usingBlock:^(NSNotification *note) {
|
||||
// NSLog( @"exit full screen %@", nsWindow );
|
||||
if( nsWindow.toolbar != NULL ) {
|
||||
setWindowButtonsHidden( nsWindow, false );
|
||||
nsWindow.toolbar.visible = YES;
|
||||
}
|
||||
|
||||
windowData.lastWindowButtonAreaWidth = 0;
|
||||
windowData.lastWindowTitleBarHeight = 0;
|
||||
}];
|
||||
} else if( !needsToolbar ) {
|
||||
// NSLog( @"remove observers %@", nsWindow );
|
||||
if( windowData.willEnterFullScreenObserver != NULL ) {
|
||||
[center removeObserver:windowData.willEnterFullScreenObserver];
|
||||
windowData.willEnterFullScreenObserver = nil;
|
||||
}
|
||||
if( windowData.willExitFullScreenObserver != NULL ) {
|
||||
[center removeObserver:windowData.willExitFullScreenObserver];
|
||||
windowData.willExitFullScreenObserver = nil;
|
||||
}
|
||||
if( windowData.didExitFullScreenObserver != NULL ) {
|
||||
[center removeObserver:windowData.didExitFullScreenObserver];
|
||||
windowData.didExitFullScreenObserver = nil;
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
return TRUE;
|
||||
|
||||
JNI_COCOA_EXIT()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden ) {
|
||||
// get buttons
|
||||
NSView* buttons[3] = {
|
||||
[nsWindow standardWindowButton:NSWindowCloseButton],
|
||||
[nsWindow standardWindowButton:NSWindowMiniaturizeButton],
|
||||
[nsWindow standardWindowButton:NSWindowZoomButton]
|
||||
};
|
||||
|
||||
for( int i = 0; i < 3; i++ ) {
|
||||
NSView* button = buttons[i];
|
||||
if( button != NULL )
|
||||
button.hidden = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWindowButtonsBounds
|
||||
( JNIEnv* env, jclass cls, jobject window )
|
||||
{
|
||||
JNI_COCOA_ENTER()
|
||||
|
||||
NSWindow* nsWindow = getNSWindow( env, cls, window );
|
||||
if( nsWindow == NULL )
|
||||
return NULL;
|
||||
|
||||
WindowData* windowData = getWindowData( nsWindow, false );
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
// get width
|
||||
if( isWindowFullScreen( nsWindow ) ) {
|
||||
// use zero if window is full screen because close/minimize/zoom buttons are hidden
|
||||
width = 0;
|
||||
} else if( windowData != NULL && windowData.lastWindowButtonAreaWidth > 0 ) {
|
||||
// use remembered value if window is in transition from full screen to non-full screen
|
||||
// because NSToolbar is not yet visible
|
||||
width = windowData.lastWindowButtonAreaWidth;
|
||||
} else
|
||||
width = getWindowButtonAreaWidth( nsWindow );
|
||||
|
||||
// get height
|
||||
if( windowData != NULL && windowData.lastWindowTitleBarHeight > 0 ) {
|
||||
// use remembered value if window is full screen because NSToolbar is hidden
|
||||
height = windowData.lastWindowTitleBarHeight;
|
||||
} else
|
||||
height = getWindowTitleBarHeight( nsWindow );
|
||||
|
||||
// initialize class and method ID (done only once because variables are static)
|
||||
static jclass cls = findClass( env, "java/awt/Rectangle", true );
|
||||
static jmethodID methodID = getMethodID( env, cls, "<init>", "(IIII)V", false );
|
||||
if( cls == NULL || methodID == NULL )
|
||||
return NULL;
|
||||
|
||||
// create and return Rectangle
|
||||
return env->NewObject( cls, methodID, 0, 0, width, height );
|
||||
|
||||
JNI_COCOA_EXIT()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int getWindowButtonAreaWidth( NSWindow* nsWindow ) {
|
||||
// get buttons
|
||||
NSView* buttons[3] = {
|
||||
[nsWindow standardWindowButton:NSWindowCloseButton],
|
||||
[nsWindow standardWindowButton:NSWindowMiniaturizeButton],
|
||||
[nsWindow standardWindowButton:NSWindowZoomButton]
|
||||
};
|
||||
|
||||
// get most left and right coordinates
|
||||
int left = -1;
|
||||
int right = -1;
|
||||
for( int i = 0; i < 3; i++ ) {
|
||||
NSView* button = buttons[i];
|
||||
if( button == NULL )
|
||||
continue;
|
||||
|
||||
int x = [button convertRect: [button bounds] toView:button.superview].origin.x;
|
||||
int width = button.bounds.size.width;
|
||||
if( left == -1 || x < left )
|
||||
left = x;
|
||||
if( right == -1 || x + width > right )
|
||||
right = x + width;
|
||||
}
|
||||
|
||||
if( left == -1 || right == -1 )
|
||||
return -1;
|
||||
|
||||
// 'right' is the actual button area width (from left window edge)
|
||||
// adding 'left' to add same empty space on right side as on left side
|
||||
return right + left;
|
||||
}
|
||||
|
||||
int getWindowTitleBarHeight( NSWindow* nsWindow ) {
|
||||
NSView* closeButton = [nsWindow standardWindowButton:NSWindowCloseButton];
|
||||
if( closeButton == NULL )
|
||||
return -1;
|
||||
|
||||
NSView* titlebar = closeButton.superview;
|
||||
return titlebar.bounds.size.height;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_isWindowFullScreen
|
||||
( JNIEnv* env, jclass cls, jobject window )
|
||||
{
|
||||
JNI_COCOA_ENTER()
|
||||
|
||||
NSWindow* nsWindow = getNSWindow( env, cls, window );
|
||||
if( nsWindow == NULL )
|
||||
return FALSE;
|
||||
|
||||
return (jboolean) isWindowFullScreen( nsWindow );
|
||||
|
||||
JNI_COCOA_EXIT()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool isWindowFullScreen( NSWindow* nsWindow ) {
|
||||
return ((nsWindow.styleMask & NSWindowStyleMaskFullScreen) != 0);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_toggleWindowFullScreen
|
||||
( JNIEnv* env, jclass cls, jobject window )
|
||||
{
|
||||
JNI_COCOA_ENTER()
|
||||
|
||||
NSWindow* nsWindow = getNSWindow( env, cls, window );
|
||||
if( nsWindow == NULL )
|
||||
return FALSE;
|
||||
|
||||
[FlatJNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
|
||||
[nsWindow toggleFullScreen:nil];
|
||||
}];
|
||||
|
||||
return TRUE;
|
||||
|
||||
JNI_COCOA_EXIT()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ dependencies {
|
||||
implementation( libs.jide.oss )
|
||||
implementation( libs.glazedlists )
|
||||
implementation( libs.netbeans.api.awt )
|
||||
|
||||
components.all<TargetJvmVersion8Rule>()
|
||||
}
|
||||
|
||||
applyLafs()
|
||||
@@ -58,3 +60,13 @@ fun applyLafs() {
|
||||
dependencies.implementation( parts[2] )
|
||||
}
|
||||
}
|
||||
|
||||
// rule that overrides 'org.gradle.jvm.version' with '8'
|
||||
// (required for Radiance, which requires Java 9, but FlatLaf build uses Java 8)
|
||||
abstract class TargetJvmVersion8Rule : ComponentMetadataRule {
|
||||
override fun execute( context: ComponentMetadataContext ) {
|
||||
context.details.allVariants {
|
||||
attributes.attribute( TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8 )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1111,6 +1111,7 @@ Table.dropCellBackground [lazy] #3c588b HSL 219 40 39 javax.swing.pl
|
||||
Table.dropCellForeground [lazy] #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineColor [lazy] #6d8ac0 HSL 219 40 59 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineShortColor [lazy] #b4c3df HSL 219 40 79 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.editorSelectAllOnStartEditing true
|
||||
Table.focusCellBackground #46494b HSL 204 3 28 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellHighlightBorder [lazy] 2,3,2,3 false com.formdev.flatlaf.ui.FlatTableCellBorder$Focused [UI] lineColor=#6d8ac0 HSL 219 40 59 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
@@ -1119,6 +1120,7 @@ Table.font [active] $defaultFont [UI]
|
||||
Table.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.gridColor #5a5e60 HSL 200 3 36 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI]
|
||||
Table.paintOutsideAlternateRows false
|
||||
Table.rowHeight 20
|
||||
Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI]
|
||||
Table.selectionBackground #4b6eaf HSL 219 40 49 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1264,7 +1266,6 @@ TitlePane.inactiveBackground #303234 HSL 210 4 20 javax.swing.plaf.Colo
|
||||
TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.ColorUIResource [UI]
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarResizeHeight 4
|
||||
TitlePane.menuBarTitleGap 40
|
||||
TitlePane.menuBarTitleMinimumGap 12
|
||||
TitlePane.noIconLeftGap 8
|
||||
|
||||
@@ -1116,6 +1116,7 @@ Table.dropCellBackground [lazy] #3f8fd9 HSL 209 67 55 javax.swing.pl
|
||||
Table.dropCellForeground [lazy] #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineColor [lazy] #6aa7e1 HSL 209 66 65 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineShortColor [lazy] #15416a HSL 209 67 25 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.editorSelectAllOnStartEditing true
|
||||
Table.focusCellBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellHighlightBorder [lazy] 2,3,2,3 false com.formdev.flatlaf.ui.FlatTableCellBorder$Focused [UI] lineColor=#15416a HSL 209 67 25 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
@@ -1124,6 +1125,7 @@ Table.font [active] $defaultFont [UI]
|
||||
Table.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.gridColor #ebebeb HSL 0 0 92 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI]
|
||||
Table.paintOutsideAlternateRows false
|
||||
Table.rowHeight 20
|
||||
Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI]
|
||||
Table.selectionBackground #2675bf HSL 209 67 45 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1269,7 +1271,6 @@ TitlePane.inactiveBackground #ffffff HSL 0 0 100 javax.swing.plaf.Colo
|
||||
TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.ColorUIResource [UI]
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarResizeHeight 4
|
||||
TitlePane.menuBarTitleGap 40
|
||||
TitlePane.menuBarTitleMinimumGap 12
|
||||
TitlePane.noIconLeftGap 8
|
||||
|
||||
@@ -322,7 +322,7 @@ OS Windows 10
|
||||
#---- javax.swing.JMenuBar ----
|
||||
|
||||
1 javax.swing.plaf.basic.LazyActionMap [UI]
|
||||
takeFocus com.formdev.flatlaf.ui.FlatMenuBarUI$TakeFocus (null)
|
||||
takeFocus com.formdev.flatlaf.ui.FlatMenuBarUI$TakeFocusAction
|
||||
|
||||
|
||||
#---- javax.swing.JMenuItem ----
|
||||
@@ -613,7 +613,7 @@ OS Windows 10
|
||||
selectPreviousRowCell javax.swing.plaf.basic.BasicTableUI$Actions
|
||||
selectPreviousRowChangeLead javax.swing.plaf.basic.BasicTableUI$Actions
|
||||
selectPreviousRowExtendSelection javax.swing.plaf.basic.BasicTableUI$Actions
|
||||
startEditing javax.swing.plaf.basic.BasicTableUI$Actions
|
||||
startEditing com.formdev.flatlaf.ui.FlatTableUI$StartEditingAction
|
||||
toggleAndAnchor javax.swing.plaf.basic.BasicTableUI$Actions
|
||||
|
||||
|
||||
|
||||
@@ -1121,6 +1121,7 @@ Table.dropCellBackground [lazy] #003f99 HSL 215 100 30 javax.swing.pl
|
||||
Table.dropCellForeground [lazy] #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineColor [lazy] #0069ff HSL 215 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineShortColor [lazy] #66a5ff HSL 215 100 70 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.editorSelectAllOnStartEditing true
|
||||
Table.focusCellBackground #282828 HSL 0 0 16 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellForeground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellHighlightBorder [lazy] 2,3,2,3 false com.formdev.flatlaf.ui.FlatTableCellBorder$Focused [UI] lineColor=#0069ff HSL 215 100 50 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
@@ -1129,6 +1130,7 @@ Table.font [active] $defaultFont [UI]
|
||||
Table.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.gridColor #3c3c3c HSL 0 0 24 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI]
|
||||
Table.paintOutsideAlternateRows false
|
||||
Table.rowHeight 20
|
||||
Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI]
|
||||
Table.selectionBackground #0054cc HSL 215 100 40 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1274,7 +1276,6 @@ TitlePane.inactiveBackground #323232 HSL 0 0 20 javax.swing.plaf.Colo
|
||||
TitlePane.inactiveForeground #9a9a9a HSL 0 0 60 javax.swing.plaf.ColorUIResource [UI]
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarResizeHeight 4
|
||||
TitlePane.menuBarTitleGap 40
|
||||
TitlePane.menuBarTitleMinimumGap 12
|
||||
TitlePane.noIconLeftGap 8
|
||||
|
||||
@@ -1125,6 +1125,7 @@ Table.dropCellBackground [lazy] #1a79ff HSL 215 100 55 javax.swing.pl
|
||||
Table.dropCellForeground [lazy] #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineColor [lazy] #4d97ff HSL 215 100 65 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineShortColor [lazy] #003580 HSL 215 100 25 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.editorSelectAllOnStartEditing true
|
||||
Table.focusCellBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellForeground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellHighlightBorder [lazy] 2,3,2,3 false com.formdev.flatlaf.ui.FlatTableCellBorder$Focused [UI] lineColor=#003580 HSL 215 100 25 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
@@ -1133,6 +1134,7 @@ Table.font [active] $defaultFont [UI]
|
||||
Table.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.gridColor #ebebeb HSL 0 0 92 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI]
|
||||
Table.paintOutsideAlternateRows false
|
||||
Table.rowHeight 20
|
||||
Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI]
|
||||
Table.selectionBackground #005fe6 HSL 215 100 45 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1278,7 +1280,6 @@ TitlePane.inactiveBackground #ececec HSL 0 0 93 javax.swing.plaf.Colo
|
||||
TitlePane.inactiveForeground #b6b6b6 HSL 0 0 71 javax.swing.plaf.ColorUIResource [UI]
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarResizeHeight 4
|
||||
TitlePane.menuBarTitleGap 40
|
||||
TitlePane.menuBarTitleMinimumGap 12
|
||||
TitlePane.noIconLeftGap 8
|
||||
|
||||
@@ -1149,6 +1149,7 @@ Table.dropCellBackground #ff0000 HSL 0 100 50 javax.swing.plaf.Colo
|
||||
Table.dropCellForeground #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.dropLineShortColor #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.editorSelectAllOnStartEditing true
|
||||
Table.focusCellBackground #fffff0 HSL 60 100 97 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellForeground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.focusCellHighlightBorder [lazy] 2,3,2,3 false com.formdev.flatlaf.ui.FlatTableCellBorder$Focused [UI] lineColor=#ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] lineThickness=1.000000
|
||||
@@ -1157,6 +1158,7 @@ Table.font [active] $defaultFont [UI]
|
||||
Table.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.gridColor #00ffff HSL 180 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI]
|
||||
Table.paintOutsideAlternateRows false
|
||||
Table.rowHeight 25
|
||||
Table.scrollPaneBorder [lazy] 1,9,1,9 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI]
|
||||
Table.selectionBackground #00aa00 HSL 120 100 33 javax.swing.plaf.ColorUIResource [UI]
|
||||
@@ -1305,7 +1307,6 @@ TitlePane.inactiveBackground #008800 HSL 120 100 27 javax.swing.plaf.Colo
|
||||
TitlePane.inactiveForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
|
||||
TitlePane.menuBarEmbedded true
|
||||
TitlePane.menuBarResizeHeight 4
|
||||
TitlePane.menuBarTitleGap 40
|
||||
TitlePane.menuBarTitleMinimumGap 12
|
||||
TitlePane.noIconLeftGap 8
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
org.pushingpixels.substance.api.skin.SubstanceBusinessLookAndFeel = Substance Business;ctrl F5;org.pushing-pixels:radiance-substance:3.5.1
|
||||
org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel = Substance Graphite Aqua;ctrl F6
|
||||
com.alee.laf.WebLookAndFeel = WebLaf;ctrl F11;com.weblookandfeel:weblaf-ui:1.2.13
|
||||
org.pushingpixels.radiance.theming.api.skin.RadianceBusinessLookAndFeel = Radiance Business;ctrl F5;org.pushing-pixels:radiance-theming:7.0.1
|
||||
org.pushingpixels.radiance.theming.api.skin.RadianceGraphiteAquaLookAndFeel = Radiance Graphite Aqua;ctrl F6
|
||||
com.alee.laf.WebLookAndFeel = WebLaf;ctrl F11;com.weblookandfeel:weblaf-ui:1.2.14
|
||||
com.jgoodies.looks.plastic.PlasticLookAndFeel = JGoodies Looks Plastic;ctrl F12;com.jgoodies:jgoodies-looks:2.7.0
|
||||
com.jgoodies.looks.windows.WindowsLookAndFeel = JGoodies Looks Windows;ctrl F9
|
||||
mdlaf.MaterialLookAndFeel = Material-UI-Swing;shift F11;io.github.vincenzopalazzo:material-ui-swing:1.1.4
|
||||
com.github.weisj.darklaf.DarkLaf = DarkLaf;shift F12;com.github.weisj:darklaf-core:3.0.2
|
||||
com.github.weisj.darklaf.theme.laf.DarculaThemeDarklafLookAndFeel = DarkLaf Darcula;ctrl shift F12
|
||||
com.jtattoo.plaf.smart.SmartLookAndFeel = JTattoo;ctrl shift F11;com.jtattoo:JTattoo:1.6.13
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* http://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.testing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import com.formdev.flatlaf.icons.FlatFileChooserHomeFolderIcon;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatChooserTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
// Locale.setDefault( Locale.FRENCH );
|
||||
// Locale.setDefault( Locale.GERMAN );
|
||||
// Locale.setDefault( Locale.ITALIAN );
|
||||
// Locale.setDefault( Locale.JAPANESE );
|
||||
// Locale.setDefault( Locale.SIMPLIFIED_CHINESE );
|
||||
// Locale.setDefault( Locale.TRADITIONAL_CHINESE );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
|
||||
|
||||
UIManager.put( "FileChooser.shortcuts.filesFunction", (Function<File[], File[]>) files -> {
|
||||
ArrayList<File> list = new ArrayList<>( Arrays.asList( files ) );
|
||||
list.add( 0, new File( System.getProperty( "user.home" ) ) );
|
||||
return list.toArray( new File[list.size()] );
|
||||
} );
|
||||
|
||||
UIManager.put( "FileChooser.shortcuts.displayNameFunction", (Function<File, String>) file -> {
|
||||
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
|
||||
return "Home";
|
||||
return null;
|
||||
} );
|
||||
UIManager.put( "FileChooser.shortcuts.iconFunction", (Function<File, Icon>) file -> {
|
||||
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
|
||||
return new FlatFileChooserHomeFolderIcon();
|
||||
return null;
|
||||
} );
|
||||
|
||||
frame.showFrame( FlatChooserTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatChooserTest() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void showShortcuts() {
|
||||
UIManager.put( "FileChooser.noPlacesBar", !showShortcutsCheckBox.isSelected() ? true : null );
|
||||
fileChooser1.updateUI();
|
||||
}
|
||||
|
||||
private void showAccessory() {
|
||||
JPanel accessory = null;
|
||||
if( showAccessoryCheckBox.isSelected() ) {
|
||||
accessory = new JPanel( new BorderLayout() );
|
||||
accessory.setBackground( Color.green );
|
||||
accessory.add( new JLabel( " Accessory " ), BorderLayout.CENTER );
|
||||
}
|
||||
fileChooser1.setAccessory( accessory );
|
||||
fileChooser1.revalidate();
|
||||
fileChooser1.repaint();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel colorChooserLabel = new JLabel();
|
||||
JPanel panel2 = new JPanel();
|
||||
JColorChooser colorChooser1 = new JColorChooser();
|
||||
JLabel fileChooserLabel = new JLabel();
|
||||
JPanel panel1 = new JPanel();
|
||||
fileChooser1 = new JFileChooser();
|
||||
JPanel panel3 = new JPanel();
|
||||
showShortcutsCheckBox = new JCheckBox();
|
||||
showAccessoryCheckBox = new JCheckBox();
|
||||
JLabel label1 = new JLabel();
|
||||
JLabel label2 = new JLabel();
|
||||
JLabel label3 = new JLabel();
|
||||
JLabel label4 = new JLabel();
|
||||
JLabel label5 = new JLabel();
|
||||
JLabel label6 = new JLabel();
|
||||
JLabel label7 = new JLabel();
|
||||
JLabel label8 = new JLabel();
|
||||
JLabel label9 = new JLabel();
|
||||
JLabel label10 = new JLabel();
|
||||
JLabel label11 = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[grow]",
|
||||
// rows
|
||||
"[top]" +
|
||||
"[grow,fill]" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//---- colorChooserLabel ----
|
||||
colorChooserLabel.setText("JColorChooser:");
|
||||
add(colorChooserLabel, "cell 0 0");
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setBorder(new MatteBorder(4, 4, 4, 4, Color.red));
|
||||
panel2.setLayout(new BorderLayout());
|
||||
panel2.add(colorChooser1, BorderLayout.CENTER);
|
||||
}
|
||||
add(panel2, "cell 1 0");
|
||||
|
||||
//---- fileChooserLabel ----
|
||||
fileChooserLabel.setText("JFileChooser:");
|
||||
add(fileChooserLabel, "cell 0 1,aligny top,growy 0");
|
||||
|
||||
//======== panel1 ========
|
||||
{
|
||||
panel1.setBorder(new MatteBorder(4, 4, 4, 4, Color.red));
|
||||
panel1.setLayout(new BorderLayout());
|
||||
panel1.add(fileChooser1, BorderLayout.CENTER);
|
||||
}
|
||||
add(panel1, "cell 1 1,growx");
|
||||
|
||||
//======== panel3 ========
|
||||
{
|
||||
panel3.setLayout(new MigLayout(
|
||||
"hidemode 3",
|
||||
// columns
|
||||
"[fill]" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]"));
|
||||
|
||||
//---- showShortcutsCheckBox ----
|
||||
showShortcutsCheckBox.setText("Show Shortcuts");
|
||||
showShortcutsCheckBox.setSelected(true);
|
||||
showShortcutsCheckBox.addActionListener(e -> showShortcuts());
|
||||
panel3.add(showShortcutsCheckBox, "cell 0 0");
|
||||
|
||||
//---- showAccessoryCheckBox ----
|
||||
showAccessoryCheckBox.setText("Show Accessory");
|
||||
showAccessoryCheckBox.addActionListener(e -> showAccessory());
|
||||
panel3.add(showAccessoryCheckBox, "cell 1 0");
|
||||
}
|
||||
add(panel3, "cell 1 2");
|
||||
|
||||
//---- label1 ----
|
||||
label1.setText("icons:");
|
||||
add(label1, "cell 0 3");
|
||||
|
||||
//---- label2 ----
|
||||
label2.setIcon(UIManager.getIcon("FileView.directoryIcon"));
|
||||
add(label2, "cell 1 3");
|
||||
|
||||
//---- label3 ----
|
||||
label3.setIcon(UIManager.getIcon("FileView.fileIcon"));
|
||||
add(label3, "cell 1 3");
|
||||
|
||||
//---- label4 ----
|
||||
label4.setIcon(UIManager.getIcon("FileView.computerIcon"));
|
||||
add(label4, "cell 1 3");
|
||||
|
||||
//---- label5 ----
|
||||
label5.setIcon(UIManager.getIcon("FileView.hardDriveIcon"));
|
||||
add(label5, "cell 1 3");
|
||||
|
||||
//---- label6 ----
|
||||
label6.setIcon(UIManager.getIcon("FileView.floppyDriveIcon"));
|
||||
add(label6, "cell 1 3");
|
||||
|
||||
//---- label7 ----
|
||||
label7.setIcon(UIManager.getIcon("FileChooser.newFolderIcon"));
|
||||
add(label7, "cell 1 3");
|
||||
|
||||
//---- label8 ----
|
||||
label8.setIcon(UIManager.getIcon("FileChooser.upFolderIcon"));
|
||||
add(label8, "cell 1 3");
|
||||
|
||||
//---- label9 ----
|
||||
label9.setIcon(UIManager.getIcon("FileChooser.homeFolderIcon"));
|
||||
add(label9, "cell 1 3");
|
||||
|
||||
//---- label10 ----
|
||||
label10.setIcon(UIManager.getIcon("FileChooser.detailsViewIcon"));
|
||||
add(label10, "cell 1 3");
|
||||
|
||||
//---- label11 ----
|
||||
label11.setIcon(UIManager.getIcon("FileChooser.listViewIcon"));
|
||||
add(label11, "cell 1 3");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JFileChooser fileChooser1;
|
||||
private JCheckBox showShortcutsCheckBox;
|
||||
private JCheckBox showAccessoryCheckBox;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
JFDML JFormDesigner: "8.0.0.0.194" Java: "17.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][grow]"
|
||||
"$rowConstraints": "[top][grow,fill][][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "colorChooserLabel"
|
||||
"text": "JColorChooser:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel2"
|
||||
"border": new javax.swing.border.MatteBorder( 4, 4, 4, 4, sfield java.awt.Color red )
|
||||
add( new FormComponent( "javax.swing.JColorChooser" ) {
|
||||
name: "colorChooser1"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fileChooserLabel"
|
||||
"text": "JFileChooser:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,aligny top,growy 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel1"
|
||||
"border": new javax.swing.border.MatteBorder( 4, 4, 4, 4, sfield java.awt.Color red )
|
||||
add( new FormComponent( "javax.swing.JFileChooser" ) {
|
||||
name: "fileChooser1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1,growx"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[fill][fill]"
|
||||
"$rowConstraints": "[]"
|
||||
} ) {
|
||||
name: "panel3"
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showShortcutsCheckBox"
|
||||
"text": "Show Shortcuts"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showShortcuts", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showAccessoryCheckBox"
|
||||
"text": "Show Accessory"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showAccessory", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label1"
|
||||
"text": "icons:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label2"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.directoryIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.fileIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label4"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.computerIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label5"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.hardDriveIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label6"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.floppyDriveIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label7"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.newFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label8"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.upFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label9"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.homeFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label10"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.detailsViewIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label11"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.listViewIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 790 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* http://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.testing;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatColorChooserTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
// Locale.setDefault( Locale.FRENCH );
|
||||
// Locale.setDefault( Locale.GERMAN );
|
||||
// Locale.setDefault( Locale.ITALIAN );
|
||||
// Locale.setDefault( Locale.JAPANESE );
|
||||
// Locale.setDefault( Locale.SIMPLIFIED_CHINESE );
|
||||
// Locale.setDefault( Locale.TRADITIONAL_CHINESE );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatColorChooserTest" );
|
||||
frame.showFrame( FlatColorChooserTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatColorChooserTest() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel colorChooserLabel = new JLabel();
|
||||
JPanel panel2 = new JPanel();
|
||||
JColorChooser colorChooser1 = new JColorChooser();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[grow]",
|
||||
// rows
|
||||
"[top]"));
|
||||
|
||||
//---- colorChooserLabel ----
|
||||
colorChooserLabel.setText("JColorChooser:");
|
||||
add(colorChooserLabel, "cell 0 0");
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setBorder(new MatteBorder(4, 4, 4, 4, Color.red));
|
||||
panel2.setLayout(new BorderLayout());
|
||||
panel2.add(colorChooser1, BorderLayout.CENTER);
|
||||
}
|
||||
add(panel2, "cell 1 0");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][grow]"
|
||||
"$rowConstraints": "[top]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "colorChooserLabel"
|
||||
"text": "JColorChooser:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel2"
|
||||
"border": new javax.swing.border.MatteBorder( 4, 4, 4, 4, sfield java.awt.Color red )
|
||||
add( new FormComponent( "javax.swing.JColorChooser" ) {
|
||||
name: "colorChooser1"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 790 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
*
|
||||
* http://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.testing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.icons.FlatFileChooserHomeFolderIcon;
|
||||
import com.formdev.flatlaf.ui.JavaCompatibility2;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatFileChooserTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
// Locale.setDefault( Locale.FRENCH );
|
||||
// Locale.setDefault( Locale.GERMAN );
|
||||
// Locale.setDefault( Locale.ITALIAN );
|
||||
// Locale.setDefault( Locale.JAPANESE );
|
||||
// Locale.setDefault( Locale.SIMPLIFIED_CHINESE );
|
||||
// Locale.setDefault( Locale.TRADITIONAL_CHINESE );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatFileChooserTest" );
|
||||
|
||||
UIManager.put( "FileChooser.shortcuts.filesFunction", (Function<File[], File[]>) files -> {
|
||||
ArrayList<File> list = new ArrayList<>( Arrays.asList( files ) );
|
||||
list.add( 0, new File( System.getProperty( "user.home" ) ) );
|
||||
return list.toArray( new File[list.size()] );
|
||||
} );
|
||||
|
||||
UIManager.put( "FileChooser.shortcuts.displayNameFunction", (Function<File, String>) file -> {
|
||||
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
|
||||
return "Home";
|
||||
return null;
|
||||
} );
|
||||
UIManager.put( "FileChooser.shortcuts.iconFunction", (Function<File, Icon>) file -> {
|
||||
if( file.getAbsolutePath().equals( System.getProperty( "user.home" ) ) )
|
||||
return new FlatFileChooserHomeFolderIcon();
|
||||
return null;
|
||||
} );
|
||||
|
||||
frame.showFrame( FlatFileChooserTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatFileChooserTest() {
|
||||
initComponents();
|
||||
|
||||
dialogTypeField.init( DialogType.class, false );
|
||||
fileSelectionModeField.init( FileSelectionMode.class, false );
|
||||
localesField.init( Locales.class, false );
|
||||
|
||||
showControlButtonsCheckBox.setSelected( fileChooser1.getControlButtonsAreShown() );
|
||||
multiSelectionCheckBox.setSelected( fileChooser1.isMultiSelectionEnabled() );
|
||||
fileHidingCheckBox.setSelected( fileChooser1.isFileHidingEnabled() );
|
||||
dragCheckBox.setSelected( fileChooser1.getDragEnabled() );
|
||||
filterAllFilesCheckBox.setSelected( fileChooser1.isAcceptAllFileFilterUsed() );
|
||||
|
||||
updateOutput();
|
||||
}
|
||||
|
||||
private void fileChooser1PropertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
|
||||
case JFileChooser.SELECTED_FILE_CHANGED_PROPERTY:
|
||||
case JFileChooser.SELECTED_FILES_CHANGED_PROPERTY:
|
||||
updateOutput();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOutput() {
|
||||
currentDirectoryField.setText( String.valueOf( fileChooser1.getCurrentDirectory() ) );
|
||||
selectedFileField.setText( String.valueOf( fileChooser1.getSelectedFile() ) );
|
||||
selectedFilesField.setText( Arrays.toString( fileChooser1.getSelectedFiles() ) );
|
||||
}
|
||||
|
||||
private void dialogTypeChanged() {
|
||||
DialogType value = dialogTypeField.getSelectedValue();
|
||||
int dialogType = (value != null) ? value.value : JFileChooser.OPEN_DIALOG;
|
||||
|
||||
if( dialogType == JFileChooser.CUSTOM_DIALOG )
|
||||
fileChooser1.setApproveButtonText( "Custom" );
|
||||
fileChooser1.setDialogType( dialogType );
|
||||
}
|
||||
|
||||
private void fileSelectionModeChanged() {
|
||||
FileSelectionMode value = fileSelectionModeField.getSelectedValue();
|
||||
int mode = (value != null) ? value.value : JFileChooser.FILES_ONLY;
|
||||
|
||||
fileChooser1.setFileSelectionMode( mode );
|
||||
}
|
||||
|
||||
private void showControlButtons() {
|
||||
fileChooser1.setControlButtonsAreShown( showControlButtonsCheckBox.isSelected() );
|
||||
fileChooser1.revalidate();
|
||||
fileChooser1.repaint();
|
||||
}
|
||||
|
||||
private void showShortcuts() {
|
||||
UIManager.put( "FileChooser.noPlacesBar", !showShortcutsCheckBox.isSelected() ? true : null );
|
||||
fileChooser1.updateUI();
|
||||
}
|
||||
|
||||
private void showAccessory() {
|
||||
JPanel accessory = null;
|
||||
if( showAccessoryCheckBox.isSelected() ) {
|
||||
accessory = new JPanel( new BorderLayout() );
|
||||
accessory.setBackground( Color.green );
|
||||
accessory.add( new JLabel( " Accessory " ), BorderLayout.CENTER );
|
||||
}
|
||||
fileChooser1.setAccessory( accessory );
|
||||
fileChooser1.revalidate();
|
||||
fileChooser1.repaint();
|
||||
}
|
||||
|
||||
private void multiSelection() {
|
||||
fileChooser1.setMultiSelectionEnabled( multiSelectionCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void fileHiding() {
|
||||
fileChooser1.setFileHidingEnabled( fileHidingCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void drag() {
|
||||
fileChooser1.setDragEnabled( dragCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private final FileFilter TEXT_FILTER = new FileNameExtensionFilter( "Text Files", "txt", "md" );
|
||||
private final FileFilter IMAGES_FILTER = new FileNameExtensionFilter( "Images", "png", "git", "jpg", "jpeg" );
|
||||
private final FileFilter LONG_DESC_FILTER = new FileNameExtensionFilter( "Some long description (.abc, .def, .ghi, .jkl)", "dummy" );
|
||||
private final FileFilter EXTRA_LONG_DESC_FILTER = new FileNameExtensionFilter( "Some super extra long description (.abc, .def, .ghi, .jkl, .mno, .pqr, .stu)", "dummy" );
|
||||
|
||||
private void filterChanged() {
|
||||
boolean all = filterAllFilesCheckBox.isSelected();
|
||||
if( all != fileChooser1.isAcceptAllFileFilterUsed() )
|
||||
fileChooser1.setAcceptAllFileFilterUsed( all );
|
||||
|
||||
addRemoveFilter( filterTextFilesCheckBox.isSelected(), TEXT_FILTER );
|
||||
addRemoveFilter( filterImagesCheckBox.isSelected(), IMAGES_FILTER );
|
||||
addRemoveFilter( filterLongDescCheckBox.isSelected(), LONG_DESC_FILTER );
|
||||
addRemoveFilter( filterExtraLongDescCheckBox.isSelected(), EXTRA_LONG_DESC_FILTER );
|
||||
}
|
||||
|
||||
private void addRemoveFilter( boolean add, FileFilter filter ) {
|
||||
if( add )
|
||||
fileChooser1.addChoosableFileFilter( filter );
|
||||
else
|
||||
fileChooser1.removeChoosableFileFilter( filter );
|
||||
}
|
||||
|
||||
private void localesChanged() {
|
||||
Locales value = localesField.getSelectedValue();
|
||||
Locale locale = (value != null) ? value.value : Locale.ENGLISH;
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
Locale.setDefault( locale );
|
||||
JComponent.setDefaultLocale( locale );
|
||||
fileChooser1.setLocale( locale );
|
||||
ResourceBundle.clearCache();
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel( UIManager.getLookAndFeel().getClass().getName() );
|
||||
FlatLaf.updateUI();
|
||||
} catch( Exception ex ) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private void printShortcutFiles() {
|
||||
printFiles( JavaCompatibility2.getChooserShortcutPanelFiles( fileChooser1.getFileSystemView() ) );
|
||||
}
|
||||
|
||||
private void printComboBoxFiles() {
|
||||
printFiles( JavaCompatibility2.getChooserComboBoxFiles( fileChooser1.getFileSystemView() ) );
|
||||
}
|
||||
|
||||
private void printRoots() {
|
||||
FileSystemView fsv = fileChooser1.getFileSystemView();
|
||||
File[] roots = fsv.getRoots();
|
||||
printFiles( roots );
|
||||
|
||||
for( File root : roots )
|
||||
printFiles( fsv.getFiles( root, true ) );
|
||||
}
|
||||
|
||||
private void printFiles( File[] files ) {
|
||||
System.out.println( "--------------------------------" );
|
||||
FileSystemView fsv = fileChooser1.getFileSystemView();
|
||||
for( File file : files ) {
|
||||
System.out.printf( "%-30s ", file );
|
||||
System.out.println(
|
||||
(fsv.isComputerNode( file ) ? "computer " : "") +
|
||||
(fsv.isDrive( file ) ? "drive " : "") +
|
||||
(fsv.isFileSystem( file ) ? "fileSystem " : "") +
|
||||
(fsv.isFileSystemRoot( file ) ? "fileSystemRoot " : "") +
|
||||
(fsv.isFloppyDrive( file ) ? "floppyDrive " : "") +
|
||||
(fsv.isHiddenFile( file ) ? "hiddenFile " : "") +
|
||||
(fsv.isRoot( file ) ? "root " : "") +
|
||||
(fsv.isTraversable( file ) ? "traversable " : "") );
|
||||
}
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel fileChooserLabel = new JLabel();
|
||||
JPanel panel1 = new JPanel();
|
||||
fileChooser1 = new JFileChooser();
|
||||
JLabel currentDirectoryLabel = new JLabel();
|
||||
currentDirectoryField = new JTextField();
|
||||
JLabel selectedFileLabel = new JLabel();
|
||||
selectedFileField = new JTextField();
|
||||
JLabel selectedFilesLabel = new JLabel();
|
||||
selectedFilesField = new JTextField();
|
||||
JLabel dialogTypeLabel = new JLabel();
|
||||
dialogTypeField = new FlatTestEnumSelector<>();
|
||||
showControlButtonsCheckBox = new JCheckBox();
|
||||
showShortcutsCheckBox = new JCheckBox();
|
||||
showAccessoryCheckBox = new JCheckBox();
|
||||
JLabel fileSelectionModeLabel = new JLabel();
|
||||
fileSelectionModeField = new FlatTestEnumSelector<>();
|
||||
multiSelectionCheckBox = new JCheckBox();
|
||||
fileHidingCheckBox = new JCheckBox();
|
||||
dragCheckBox = new JCheckBox();
|
||||
JLabel filtersLabel = new JLabel();
|
||||
filterAllFilesCheckBox = new JCheckBox();
|
||||
filterTextFilesCheckBox = new JCheckBox();
|
||||
filterImagesCheckBox = new JCheckBox();
|
||||
filterLongDescCheckBox = new JCheckBox();
|
||||
filterExtraLongDescCheckBox = new JCheckBox();
|
||||
printShortcutFilesButton = new JButton();
|
||||
printComboBoxFilesButton = new JButton();
|
||||
printRootsButton = new JButton();
|
||||
JLabel localesLabel = new JLabel();
|
||||
localesField = new FlatTestEnumSelector<>();
|
||||
JLabel label1 = new JLabel();
|
||||
JLabel label2 = new JLabel();
|
||||
JLabel label3 = new JLabel();
|
||||
JLabel label4 = new JLabel();
|
||||
JLabel label5 = new JLabel();
|
||||
JLabel label6 = new JLabel();
|
||||
JLabel label7 = new JLabel();
|
||||
JLabel label8 = new JLabel();
|
||||
JLabel label9 = new JLabel();
|
||||
JLabel label10 = new JLabel();
|
||||
JLabel label11 = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[grow]",
|
||||
// rows
|
||||
"[grow,fill]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]"));
|
||||
|
||||
//---- fileChooserLabel ----
|
||||
fileChooserLabel.setText("JFileChooser:");
|
||||
add(fileChooserLabel, "cell 0 0,aligny top,growy 0");
|
||||
|
||||
//======== panel1 ========
|
||||
{
|
||||
panel1.setBorder(new MatteBorder(4, 4, 4, 4, Color.red));
|
||||
panel1.setLayout(new BorderLayout());
|
||||
|
||||
//---- fileChooser1 ----
|
||||
fileChooser1.addPropertyChangeListener(e -> fileChooser1PropertyChange(e));
|
||||
panel1.add(fileChooser1, BorderLayout.CENTER);
|
||||
}
|
||||
add(panel1, "cell 1 0 2 1,growx");
|
||||
|
||||
//---- currentDirectoryLabel ----
|
||||
currentDirectoryLabel.setText("Current Directory:");
|
||||
add(currentDirectoryLabel, "cell 0 1");
|
||||
|
||||
//---- currentDirectoryField ----
|
||||
currentDirectoryField.setEditable(false);
|
||||
add(currentDirectoryField, "cell 1 1 2 1,growx");
|
||||
|
||||
//---- selectedFileLabel ----
|
||||
selectedFileLabel.setText("Selected File:");
|
||||
add(selectedFileLabel, "cell 0 2");
|
||||
|
||||
//---- selectedFileField ----
|
||||
selectedFileField.setEditable(false);
|
||||
add(selectedFileField, "cell 1 2 2 1,growx");
|
||||
|
||||
//---- selectedFilesLabel ----
|
||||
selectedFilesLabel.setText("Selected Files:");
|
||||
add(selectedFilesLabel, "cell 0 3");
|
||||
|
||||
//---- selectedFilesField ----
|
||||
selectedFilesField.setEditable(false);
|
||||
add(selectedFilesField, "cell 1 3 2 1,growx");
|
||||
|
||||
//---- dialogTypeLabel ----
|
||||
dialogTypeLabel.setText("Dialog Type:");
|
||||
add(dialogTypeLabel, "cell 0 4");
|
||||
|
||||
//---- dialogTypeField ----
|
||||
dialogTypeField.addActionListener(e -> dialogTypeChanged());
|
||||
add(dialogTypeField, "cell 1 4");
|
||||
|
||||
//---- showControlButtonsCheckBox ----
|
||||
showControlButtonsCheckBox.setText("Show Control Buttons");
|
||||
showControlButtonsCheckBox.addActionListener(e -> showControlButtons());
|
||||
add(showControlButtonsCheckBox, "cell 2 4");
|
||||
|
||||
//---- showShortcutsCheckBox ----
|
||||
showShortcutsCheckBox.setText("Show Shortcuts");
|
||||
showShortcutsCheckBox.setSelected(true);
|
||||
showShortcutsCheckBox.addActionListener(e -> showShortcuts());
|
||||
add(showShortcutsCheckBox, "cell 2 4");
|
||||
|
||||
//---- showAccessoryCheckBox ----
|
||||
showAccessoryCheckBox.setText("Show Accessory");
|
||||
showAccessoryCheckBox.addActionListener(e -> showAccessory());
|
||||
add(showAccessoryCheckBox, "cell 2 4");
|
||||
|
||||
//---- fileSelectionModeLabel ----
|
||||
fileSelectionModeLabel.setText("File Selection Mode:");
|
||||
add(fileSelectionModeLabel, "cell 0 5");
|
||||
|
||||
//---- fileSelectionModeField ----
|
||||
fileSelectionModeField.addActionListener(e -> fileSelectionModeChanged());
|
||||
add(fileSelectionModeField, "cell 1 5");
|
||||
|
||||
//---- multiSelectionCheckBox ----
|
||||
multiSelectionCheckBox.setText("Multi Selection");
|
||||
multiSelectionCheckBox.addActionListener(e -> multiSelection());
|
||||
add(multiSelectionCheckBox, "cell 2 5");
|
||||
|
||||
//---- fileHidingCheckBox ----
|
||||
fileHidingCheckBox.setText("File Hiding");
|
||||
fileHidingCheckBox.addActionListener(e -> fileHiding());
|
||||
add(fileHidingCheckBox, "cell 2 5");
|
||||
|
||||
//---- dragCheckBox ----
|
||||
dragCheckBox.setText("Drag");
|
||||
dragCheckBox.addActionListener(e -> drag());
|
||||
add(dragCheckBox, "cell 2 5");
|
||||
|
||||
//---- filtersLabel ----
|
||||
filtersLabel.setText("Filters:");
|
||||
add(filtersLabel, "cell 0 6");
|
||||
|
||||
//---- filterAllFilesCheckBox ----
|
||||
filterAllFilesCheckBox.setText("All Files");
|
||||
filterAllFilesCheckBox.addActionListener(e -> filterChanged());
|
||||
add(filterAllFilesCheckBox, "cell 1 6 2 1");
|
||||
|
||||
//---- filterTextFilesCheckBox ----
|
||||
filterTextFilesCheckBox.setText("Text Files");
|
||||
filterTextFilesCheckBox.addActionListener(e -> filterChanged());
|
||||
add(filterTextFilesCheckBox, "cell 1 6 2 1");
|
||||
|
||||
//---- filterImagesCheckBox ----
|
||||
filterImagesCheckBox.setText("Images");
|
||||
filterImagesCheckBox.addActionListener(e -> filterChanged());
|
||||
add(filterImagesCheckBox, "cell 1 6 2 1");
|
||||
|
||||
//---- filterLongDescCheckBox ----
|
||||
filterLongDescCheckBox.setText("Long description");
|
||||
filterLongDescCheckBox.addActionListener(e -> filterChanged());
|
||||
add(filterLongDescCheckBox, "cell 1 6 2 1");
|
||||
|
||||
//---- filterExtraLongDescCheckBox ----
|
||||
filterExtraLongDescCheckBox.setText("Extra Long description");
|
||||
filterExtraLongDescCheckBox.addActionListener(e -> filterChanged());
|
||||
add(filterExtraLongDescCheckBox, "cell 1 6 2 1");
|
||||
|
||||
//---- printShortcutFilesButton ----
|
||||
printShortcutFilesButton.setText("Print Shortcut Files");
|
||||
printShortcutFilesButton.addActionListener(e -> printShortcutFiles());
|
||||
add(printShortcutFilesButton, "cell 1 7 2 1");
|
||||
|
||||
//---- printComboBoxFilesButton ----
|
||||
printComboBoxFilesButton.setText("Print ComboBox Files");
|
||||
printComboBoxFilesButton.addActionListener(e -> printComboBoxFiles());
|
||||
add(printComboBoxFilesButton, "cell 1 7 2 1");
|
||||
|
||||
//---- printRootsButton ----
|
||||
printRootsButton.setText("Print Roots");
|
||||
printRootsButton.addActionListener(e -> printRoots());
|
||||
add(printRootsButton, "cell 1 7 2 1");
|
||||
|
||||
//---- localesLabel ----
|
||||
localesLabel.setText("Locales:");
|
||||
add(localesLabel, "cell 0 8");
|
||||
|
||||
//---- localesField ----
|
||||
localesField.addActionListener(e -> localesChanged());
|
||||
add(localesField, "cell 1 8 2 1");
|
||||
|
||||
//---- label1 ----
|
||||
label1.setText("icons:");
|
||||
add(label1, "cell 0 9");
|
||||
|
||||
//---- label2 ----
|
||||
label2.setIcon(UIManager.getIcon("FileView.directoryIcon"));
|
||||
add(label2, "cell 1 9 2 1");
|
||||
|
||||
//---- label3 ----
|
||||
label3.setIcon(UIManager.getIcon("FileView.fileIcon"));
|
||||
add(label3, "cell 1 9 2 1");
|
||||
|
||||
//---- label4 ----
|
||||
label4.setIcon(UIManager.getIcon("FileView.computerIcon"));
|
||||
add(label4, "cell 1 9 2 1");
|
||||
|
||||
//---- label5 ----
|
||||
label5.setIcon(UIManager.getIcon("FileView.hardDriveIcon"));
|
||||
add(label5, "cell 1 9 2 1");
|
||||
|
||||
//---- label6 ----
|
||||
label6.setIcon(UIManager.getIcon("FileView.floppyDriveIcon"));
|
||||
add(label6, "cell 1 9 2 1");
|
||||
|
||||
//---- label7 ----
|
||||
label7.setIcon(UIManager.getIcon("FileChooser.newFolderIcon"));
|
||||
add(label7, "cell 1 9 2 1");
|
||||
|
||||
//---- label8 ----
|
||||
label8.setIcon(UIManager.getIcon("FileChooser.upFolderIcon"));
|
||||
add(label8, "cell 1 9 2 1");
|
||||
|
||||
//---- label9 ----
|
||||
label9.setIcon(UIManager.getIcon("FileChooser.homeFolderIcon"));
|
||||
add(label9, "cell 1 9 2 1");
|
||||
|
||||
//---- label10 ----
|
||||
label10.setIcon(UIManager.getIcon("FileChooser.detailsViewIcon"));
|
||||
add(label10, "cell 1 9 2 1");
|
||||
|
||||
//---- label11 ----
|
||||
label11.setIcon(UIManager.getIcon("FileChooser.listViewIcon"));
|
||||
add(label11, "cell 1 9 2 1");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JFileChooser fileChooser1;
|
||||
private JTextField currentDirectoryField;
|
||||
private JTextField selectedFileField;
|
||||
private JTextField selectedFilesField;
|
||||
private FlatTestEnumSelector<DialogType> dialogTypeField;
|
||||
private JCheckBox showControlButtonsCheckBox;
|
||||
private JCheckBox showShortcutsCheckBox;
|
||||
private JCheckBox showAccessoryCheckBox;
|
||||
private FlatTestEnumSelector<FileSelectionMode> fileSelectionModeField;
|
||||
private JCheckBox multiSelectionCheckBox;
|
||||
private JCheckBox fileHidingCheckBox;
|
||||
private JCheckBox dragCheckBox;
|
||||
private JCheckBox filterAllFilesCheckBox;
|
||||
private JCheckBox filterTextFilesCheckBox;
|
||||
private JCheckBox filterImagesCheckBox;
|
||||
private JCheckBox filterLongDescCheckBox;
|
||||
private JCheckBox filterExtraLongDescCheckBox;
|
||||
private JButton printShortcutFilesButton;
|
||||
private JButton printComboBoxFilesButton;
|
||||
private JButton printRootsButton;
|
||||
private FlatTestEnumSelector<Locales> localesField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- enum DialogType ----------------------------------------------------
|
||||
|
||||
enum DialogType {
|
||||
open( JFileChooser.OPEN_DIALOG ),
|
||||
save( JFileChooser.SAVE_DIALOG ),
|
||||
custom( JFileChooser.CUSTOM_DIALOG );
|
||||
|
||||
public final int value;
|
||||
|
||||
DialogType( int value ) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
//---- enum FileSelectionMode ---------------------------------------------
|
||||
|
||||
enum FileSelectionMode {
|
||||
files_only( JFileChooser.FILES_ONLY ),
|
||||
directories_only( JFileChooser.DIRECTORIES_ONLY ),
|
||||
files_and_directories( JFileChooser.FILES_AND_DIRECTORIES );
|
||||
|
||||
public final int value;
|
||||
|
||||
FileSelectionMode( int value ) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
//---- enum Locales -------------------------------------------------------
|
||||
|
||||
// locales supported by Swing
|
||||
// (see https://github.com/openjdk/jdk/tree/master/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources)
|
||||
enum Locales {
|
||||
english( Locale.ENGLISH ),
|
||||
german( Locale.GERMAN ),
|
||||
spanish( new Locale( "es" ) ),
|
||||
french( Locale.FRENCH ),
|
||||
italian( Locale.ITALIAN ),
|
||||
japanese( Locale.JAPANESE ),
|
||||
korean( Locale.KOREAN ),
|
||||
brazilian_portuguese( new Locale( "pt", "BR" ) ),
|
||||
swedish( new Locale( "sv" ) ),
|
||||
simplified_chinese( Locale.SIMPLIFIED_CHINESE ),
|
||||
traditional_chinese( Locale.TRADITIONAL_CHINESE );
|
||||
|
||||
public final Locale value;
|
||||
|
||||
Locales( Locale value ) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][][grow]"
|
||||
"$rowConstraints": "[grow,fill][][][][][][][][]para[]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fileChooserLabel"
|
||||
"text": "JFileChooser:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0,aligny top,growy 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel1"
|
||||
"border": new javax.swing.border.MatteBorder( 4, 4, 4, 4, sfield java.awt.Color red )
|
||||
add( new FormComponent( "javax.swing.JFileChooser" ) {
|
||||
name: "fileChooser1"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.beans.PropertyChangeListener", "propertyChange", "fileChooser1PropertyChange", true ) )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0 2 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "currentDirectoryLabel"
|
||||
"text": "Current Directory:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "currentDirectoryField"
|
||||
"editable": false
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1 2 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "selectedFileLabel"
|
||||
"text": "Selected File:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "selectedFileField"
|
||||
"editable": false
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2 2 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "selectedFilesLabel"
|
||||
"text": "Selected Files:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "selectedFilesField"
|
||||
"editable": false
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3 2 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "dialogTypeLabel"
|
||||
"text": "Dialog Type:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumSelector" ) {
|
||||
name: "dialogTypeField"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.typeParameters": "DialogType"
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "dialogTypeChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showControlButtonsCheckBox"
|
||||
"text": "Show Control Buttons"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showControlButtons", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showShortcutsCheckBox"
|
||||
"text": "Show Shortcuts"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showShortcuts", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showAccessoryCheckBox"
|
||||
"text": "Show Accessory"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showAccessory", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fileSelectionModeLabel"
|
||||
"text": "File Selection Mode:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumSelector" ) {
|
||||
name: "fileSelectionModeField"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.typeParameters": "FileSelectionMode"
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fileSelectionModeChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "multiSelectionCheckBox"
|
||||
"text": "Multi Selection"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "multiSelection", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "fileHidingCheckBox"
|
||||
"text": "File Hiding"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fileHiding", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "dragCheckBox"
|
||||
"text": "Drag"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "drag", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "filtersLabel"
|
||||
"text": "Filters:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "filterAllFilesCheckBox"
|
||||
"text": "All Files"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "filterChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "filterTextFilesCheckBox"
|
||||
"text": "Text Files"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "filterChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "filterImagesCheckBox"
|
||||
"text": "Images"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "filterChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "filterLongDescCheckBox"
|
||||
"text": "Long description"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "filterChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "filterExtraLongDescCheckBox"
|
||||
"text": "Extra Long description"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "filterChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "printShortcutFilesButton"
|
||||
"text": "Print Shortcut Files"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "printShortcutFiles", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "printComboBoxFilesButton"
|
||||
"text": "Print ComboBox Files"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "printComboBoxFiles", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "printRootsButton"
|
||||
"text": "Print Roots"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "printRoots", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "localesLabel"
|
||||
"text": "Locales:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 8"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumSelector" ) {
|
||||
name: "localesField"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
"JavaCodeGenerator.typeParameters": "Locales"
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "localesChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 8 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label1"
|
||||
"text": "icons:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 9"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label2"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.directoryIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.fileIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label4"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.computerIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label5"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.hardDriveIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label6"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileView.floppyDriveIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label7"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.newFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label8"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.upFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label9"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.homeFolderIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label10"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.detailsViewIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label11"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "FileChooser.listViewIcon" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 9 2 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 715, 660 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2024 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.testing;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatNativeMacLibrary;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMacOSTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, FlatMacOSTest.class.getSimpleName() );
|
||||
frame.applyComponentOrientationToFrame = true;
|
||||
|
||||
JRootPane rootPane = frame.getRootPane();
|
||||
rootPane.putClientProperty( "apple.awt.fullWindowContent", true );
|
||||
rootPane.putClientProperty( "apple.awt.transparentTitleBar", true );
|
||||
rootPane.putClientProperty( "apple.awt.windowTitleVisible", false );
|
||||
|
||||
frame.showFrame( FlatMacOSTest::new );
|
||||
} );
|
||||
}
|
||||
|
||||
FlatMacOSTest() {
|
||||
initComponents();
|
||||
|
||||
if( SystemInfo.isMacFullWindowContentSupported ) {
|
||||
fullWindowContentHint.setVisible( false );
|
||||
transparentTitleBarHint.setVisible( false );
|
||||
}
|
||||
if( SystemInfo.isJava_17_orLater ) {
|
||||
windowTitleVisibleHint.setVisible( false );
|
||||
buttonsSpacingHint.setVisible( false );
|
||||
}
|
||||
|
||||
placeholderPanel.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac zeroInFullScreen" );
|
||||
UIManager.put( "FlatLaf.debug.panel.showPlaceholders", true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
|
||||
JRootPane rootPane = getRootPane();
|
||||
fullWindowContentCheckBox.setSelected( FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.fullWindowContent", false ) );
|
||||
transparentTitleBarCheckBox.setSelected( FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.transparentTitleBar", false ) );
|
||||
windowTitleVisibleCheckBox.setSelected( FlatClientProperties.clientPropertyBoolean( rootPane, "apple.awt.windowTitleVisible", true ) );
|
||||
|
||||
rootPane.addPropertyChangeListener( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, e -> {
|
||||
Rectangle bounds = (Rectangle) e.getNewValue();
|
||||
fullWindowContentButtonsBoundsField.setText( bounds2string( bounds ) );
|
||||
} );
|
||||
updateNativeButtonBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
if( nativeButtonsBoundsField != null )
|
||||
updateNativeButtonBounds();
|
||||
}
|
||||
|
||||
private void fullWindowContentChanged() {
|
||||
getRootPane().putClientProperty( "apple.awt.fullWindowContent", fullWindowContentCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void transparentTitleBarChanged() {
|
||||
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", transparentTitleBarCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void windowTitleVisibleChanged() {
|
||||
getRootPane().putClientProperty( "apple.awt.windowTitleVisible", windowTitleVisibleCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void buttonsSpacingChanged() {
|
||||
String buttonsSpacing = null;
|
||||
if( buttonsSpacingMediumRadioButton.isSelected() )
|
||||
buttonsSpacing = FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_MEDIUM;
|
||||
else if( buttonsSpacingLargeRadioButton.isSelected() )
|
||||
buttonsSpacing = FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING_LARGE;
|
||||
|
||||
getRootPane().putClientProperty( FlatClientProperties.MACOS_WINDOW_BUTTONS_SPACING, buttonsSpacing );
|
||||
|
||||
updateNativeButtonBounds();
|
||||
}
|
||||
|
||||
private void updateNativeButtonBounds() {
|
||||
if( !FlatNativeMacLibrary.isLoaded() )
|
||||
return;
|
||||
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
Rectangle bounds = FlatNativeMacLibrary.getWindowButtonsBounds( window );
|
||||
nativeButtonsBoundsField.setText( bounds2string( bounds ) );
|
||||
}
|
||||
|
||||
private String bounds2string( Rectangle bounds ) {
|
||||
return (bounds != null)
|
||||
? bounds.width + ", " + bounds.height + " @ " + bounds.x + ", " + bounds.y
|
||||
: "null";
|
||||
}
|
||||
|
||||
private void toggleFullScreen() {
|
||||
if( !FlatNativeMacLibrary.isLoaded() )
|
||||
return;
|
||||
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
FlatNativeMacLibrary.toggleWindowFullScreen( window );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JPanel panel1 = new JPanel();
|
||||
placeholderPanel = new JPanel();
|
||||
JPanel panel2 = new JPanel();
|
||||
fullWindowContentCheckBox = new JCheckBox();
|
||||
fullWindowContentHint = new JLabel();
|
||||
transparentTitleBarCheckBox = new JCheckBox();
|
||||
transparentTitleBarHint = new JLabel();
|
||||
windowTitleVisibleCheckBox = new JCheckBox();
|
||||
windowTitleVisibleHint = new JLabel();
|
||||
JLabel buttonsSpacingLabel = new JLabel();
|
||||
buttonsSpacingDefaultRadioButton = new JRadioButton();
|
||||
buttonsSpacingMediumRadioButton = new JRadioButton();
|
||||
buttonsSpacingLargeRadioButton = new JRadioButton();
|
||||
buttonsSpacingHint = new JLabel();
|
||||
JLabel fullWindowContentButtonsBoundsLabel = new JLabel();
|
||||
fullWindowContentButtonsBoundsField = new JLabel();
|
||||
JLabel nativeButtonsBoundsLabel = new JLabel();
|
||||
nativeButtonsBoundsField = new JLabel();
|
||||
JButton toggleFullScreenButton = new JButton();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
//======== panel1 ========
|
||||
{
|
||||
panel1.setLayout(new BorderLayout());
|
||||
|
||||
//======== placeholderPanel ========
|
||||
{
|
||||
placeholderPanel.setBackground(Color.green);
|
||||
placeholderPanel.setLayout(new FlowLayout());
|
||||
}
|
||||
panel1.add(placeholderPanel, BorderLayout.WEST);
|
||||
}
|
||||
add(panel1, BorderLayout.PAGE_START);
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setLayout(new MigLayout(
|
||||
"ltr,insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[left]" +
|
||||
"[left]" +
|
||||
"[left]" +
|
||||
"[left]para" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[fill]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]"));
|
||||
|
||||
//---- fullWindowContentCheckBox ----
|
||||
fullWindowContentCheckBox.setText("fullWindowContent");
|
||||
fullWindowContentCheckBox.addActionListener(e -> fullWindowContentChanged());
|
||||
panel2.add(fullWindowContentCheckBox, "cell 0 0");
|
||||
|
||||
//---- fullWindowContentHint ----
|
||||
fullWindowContentHint.setText("requires Java 12, 11.0.8 or 8u292");
|
||||
fullWindowContentHint.setForeground(Color.red);
|
||||
panel2.add(fullWindowContentHint, "cell 4 0");
|
||||
|
||||
//---- transparentTitleBarCheckBox ----
|
||||
transparentTitleBarCheckBox.setText("transparentTitleBar");
|
||||
transparentTitleBarCheckBox.addActionListener(e -> transparentTitleBarChanged());
|
||||
panel2.add(transparentTitleBarCheckBox, "cell 0 1");
|
||||
|
||||
//---- transparentTitleBarHint ----
|
||||
transparentTitleBarHint.setText("requires Java 12, 11.0.8 or 8u292");
|
||||
transparentTitleBarHint.setForeground(Color.red);
|
||||
panel2.add(transparentTitleBarHint, "cell 4 1");
|
||||
|
||||
//---- windowTitleVisibleCheckBox ----
|
||||
windowTitleVisibleCheckBox.setText("windowTitleVisible");
|
||||
windowTitleVisibleCheckBox.addActionListener(e -> windowTitleVisibleChanged());
|
||||
panel2.add(windowTitleVisibleCheckBox, "cell 0 2");
|
||||
|
||||
//---- windowTitleVisibleHint ----
|
||||
windowTitleVisibleHint.setText("requires Java 17");
|
||||
windowTitleVisibleHint.setForeground(Color.red);
|
||||
panel2.add(windowTitleVisibleHint, "cell 4 2");
|
||||
|
||||
//---- buttonsSpacingLabel ----
|
||||
buttonsSpacingLabel.setText("Buttons spacing:");
|
||||
panel2.add(buttonsSpacingLabel, "cell 0 3");
|
||||
|
||||
//---- buttonsSpacingDefaultRadioButton ----
|
||||
buttonsSpacingDefaultRadioButton.setText("Default");
|
||||
buttonsSpacingDefaultRadioButton.setSelected(true);
|
||||
buttonsSpacingDefaultRadioButton.addActionListener(e -> buttonsSpacingChanged());
|
||||
panel2.add(buttonsSpacingDefaultRadioButton, "cell 1 3");
|
||||
|
||||
//---- buttonsSpacingMediumRadioButton ----
|
||||
buttonsSpacingMediumRadioButton.setText("Medium");
|
||||
buttonsSpacingMediumRadioButton.addActionListener(e -> buttonsSpacingChanged());
|
||||
panel2.add(buttonsSpacingMediumRadioButton, "cell 2 3");
|
||||
|
||||
//---- buttonsSpacingLargeRadioButton ----
|
||||
buttonsSpacingLargeRadioButton.setText("Large");
|
||||
buttonsSpacingLargeRadioButton.addActionListener(e -> buttonsSpacingChanged());
|
||||
panel2.add(buttonsSpacingLargeRadioButton, "cell 3 3");
|
||||
|
||||
//---- buttonsSpacingHint ----
|
||||
buttonsSpacingHint.setText("requires Java 17");
|
||||
buttonsSpacingHint.setForeground(Color.red);
|
||||
panel2.add(buttonsSpacingHint, "cell 4 3");
|
||||
|
||||
//---- fullWindowContentButtonsBoundsLabel ----
|
||||
fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:");
|
||||
panel2.add(fullWindowContentButtonsBoundsLabel, "cell 0 4");
|
||||
|
||||
//---- fullWindowContentButtonsBoundsField ----
|
||||
fullWindowContentButtonsBoundsField.setText("null");
|
||||
panel2.add(fullWindowContentButtonsBoundsField, "cell 1 4 3 1");
|
||||
|
||||
//---- nativeButtonsBoundsLabel ----
|
||||
nativeButtonsBoundsLabel.setText("Native buttons bounds:");
|
||||
panel2.add(nativeButtonsBoundsLabel, "cell 0 5");
|
||||
|
||||
//---- nativeButtonsBoundsField ----
|
||||
nativeButtonsBoundsField.setText("null");
|
||||
panel2.add(nativeButtonsBoundsField, "cell 1 5 3 1");
|
||||
|
||||
//---- toggleFullScreenButton ----
|
||||
toggleFullScreenButton.setText("Toggle Full Screen");
|
||||
toggleFullScreenButton.addActionListener(e -> toggleFullScreen());
|
||||
panel2.add(toggleFullScreenButton, "cell 0 6");
|
||||
}
|
||||
add(panel2, BorderLayout.CENTER);
|
||||
|
||||
//---- buttonsSpacingButtonGroup ----
|
||||
ButtonGroup buttonsSpacingButtonGroup = new ButtonGroup();
|
||||
buttonsSpacingButtonGroup.add(buttonsSpacingDefaultRadioButton);
|
||||
buttonsSpacingButtonGroup.add(buttonsSpacingMediumRadioButton);
|
||||
buttonsSpacingButtonGroup.add(buttonsSpacingLargeRadioButton);
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JPanel placeholderPanel;
|
||||
private JCheckBox fullWindowContentCheckBox;
|
||||
private JLabel fullWindowContentHint;
|
||||
private JCheckBox transparentTitleBarCheckBox;
|
||||
private JLabel transparentTitleBarHint;
|
||||
private JCheckBox windowTitleVisibleCheckBox;
|
||||
private JLabel windowTitleVisibleHint;
|
||||
private JRadioButton buttonsSpacingDefaultRadioButton;
|
||||
private JRadioButton buttonsSpacingMediumRadioButton;
|
||||
private JRadioButton buttonsSpacingLargeRadioButton;
|
||||
private JLabel buttonsSpacingHint;
|
||||
private JLabel fullWindowContentButtonsBoundsField;
|
||||
private JLabel nativeButtonsBoundsField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
JFDML JFormDesigner: "8.2.1.0.348" Java: "21.0.1" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "this"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel1"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||
name: "placeholderPanel"
|
||||
"background": sfield java.awt.Color green
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "West"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "First"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[left][left][left][left]para[fill]"
|
||||
"$rowConstraints": "[][][][fill][][]para[]"
|
||||
} ) {
|
||||
name: "panel2"
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "fullWindowContentCheckBox"
|
||||
"text": "fullWindowContent"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullWindowContentChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fullWindowContentHint"
|
||||
"text": "requires Java 12, 11.0.8 or 8u292"
|
||||
"foreground": sfield java.awt.Color red
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "transparentTitleBarCheckBox"
|
||||
"text": "transparentTitleBar"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "transparentTitleBarChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "transparentTitleBarHint"
|
||||
"text": "requires Java 12, 11.0.8 or 8u292"
|
||||
"foreground": sfield java.awt.Color red
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "windowTitleVisibleCheckBox"
|
||||
"text": "windowTitleVisible"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "windowTitleVisibleChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "windowTitleVisibleHint"
|
||||
"text": "requires Java 17"
|
||||
"foreground": sfield java.awt.Color red
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "buttonsSpacingLabel"
|
||||
"text": "Buttons spacing:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
name: "buttonsSpacingDefaultRadioButton"
|
||||
"text": "Default"
|
||||
"$buttonGroup": new FormReference( "buttonsSpacingButtonGroup" )
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "buttonsSpacingChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
name: "buttonsSpacingMediumRadioButton"
|
||||
"text": "Medium"
|
||||
"$buttonGroup": new FormReference( "buttonsSpacingButtonGroup" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "buttonsSpacingChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||
name: "buttonsSpacingLargeRadioButton"
|
||||
"text": "Large"
|
||||
"$buttonGroup": new FormReference( "buttonsSpacingButtonGroup" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "buttonsSpacingChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "buttonsSpacingHint"
|
||||
"text": "requires Java 17"
|
||||
"foreground": sfield java.awt.Color red
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fullWindowContentButtonsBoundsLabel"
|
||||
"text": "Buttons bounds:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fullWindowContentButtonsBoundsField"
|
||||
"text": "null"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 4 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "nativeButtonsBoundsLabel"
|
||||
"text": "Native buttons bounds:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "nativeButtonsBoundsField"
|
||||
"text": "null"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "toggleFullScreenButton"
|
||||
"text": "Toggle Full Screen"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "toggleFullScreen", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 725, 350 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "buttonsSpacingButtonGroup"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 360 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,10 @@ public class FlatTestPanel
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
g.setColor( super.getBackground() );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
if( isOpaque() ) {
|
||||
g.setColor( super.getBackground() );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
}
|
||||
|
||||
if( isPaintBackgroundPattern() ) {
|
||||
g.setColor( Color.magenta );
|
||||
|
||||
@@ -41,6 +41,9 @@ import net.miginfocom.swing.*;
|
||||
public class FlatWindowDecorationsTest
|
||||
extends FlatTestPanel
|
||||
{
|
||||
// same as in FlatTitlePane
|
||||
private static final String KEY_DEBUG_SHOW_RECTANGLES = "FlatLaf.debug.titlebar.showRectangles";
|
||||
|
||||
public static void main( String[] args ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
if( SystemInfo.isLinux ) {
|
||||
@@ -51,7 +54,7 @@ public class FlatWindowDecorationsTest
|
||||
|
||||
FlatTestFrame frame = FlatTestFrame.create( args, "FlatWindowDecorationsTest" );
|
||||
frame.applyComponentOrientationToFrame = true;
|
||||
UIManager.put( "FlatLaf.debug.titlebar.showRectangles", true );
|
||||
UIManager.put( KEY_DEBUG_SHOW_RECTANGLES, true );
|
||||
|
||||
Class<?> cls = FlatWindowDecorationsTest.class;
|
||||
List<Image> images = Arrays.asList(
|
||||
@@ -76,6 +79,14 @@ public class FlatWindowDecorationsTest
|
||||
initComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
if( translucentWindowBackgroundCheckBox != null )
|
||||
translucentWindowBackgroundChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
@@ -109,6 +120,14 @@ public class FlatWindowDecorationsTest
|
||||
rootPane.addPropertyChangeListener( "windowDecorationStyle", e -> {
|
||||
updateDecorationStyleRadioButtons( rootPane );
|
||||
} );
|
||||
rootPane.addPropertyChangeListener( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS, e -> {
|
||||
Rectangle bounds = (Rectangle) e.getNewValue();
|
||||
if( bounds != null ) {
|
||||
fullWindowContentButtonsBoundsField.setText( bounds.width + ", " + bounds.height
|
||||
+ " @ " + bounds.x + ", " + bounds.y );
|
||||
} else
|
||||
fullWindowContentButtonsBoundsField.setText( "null" );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +256,27 @@ public class FlatWindowDecorationsTest
|
||||
}
|
||||
}
|
||||
|
||||
private void translucentWindowBackgroundChanged() {
|
||||
boolean selected = translucentWindowBackgroundCheckBox.isSelected();
|
||||
if( selected && !undecoratedCheckBox.isSelected() ) {
|
||||
undecoratedCheckBox.setSelected( true );
|
||||
undecoratedChanged();
|
||||
}
|
||||
undecoratedCheckBox.setEnabled( !selected );
|
||||
|
||||
Color background = selected
|
||||
? new Color( 100, 0, 0, 100 )
|
||||
: UIManager.getColor( "control" );
|
||||
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
window.setBackground( background );
|
||||
|
||||
for( Component c = this; c != null; c = c.getParent() ) {
|
||||
if( c instanceof JComponent )
|
||||
LookAndFeel.installProperty( (JComponent) c, "opaque", !selected );
|
||||
}
|
||||
}
|
||||
|
||||
private void addMenu() {
|
||||
JMenu menu = new JMenu( "Hello" );
|
||||
menu.add( new JMenuItem( "world" ) );
|
||||
@@ -280,12 +320,21 @@ debug*/
|
||||
JLabel caption = new JLabel( "Caption" );
|
||||
caption.setBackground( Color.green );
|
||||
caption.setOpaque( true );
|
||||
caption.putClientProperty( FlatClientProperties.COMPONENT_TITLE_BAR_CAPTION, true );
|
||||
|
||||
menuBar.add( caption );
|
||||
menuBar.revalidate();
|
||||
}
|
||||
|
||||
private void addTextField() {
|
||||
JTextField textField = new JTextField( "text", 10 );
|
||||
|
||||
JPanel panel = new JPanel( new GridBagLayout() );
|
||||
panel.add( textField, new GridBagConstraints() );
|
||||
|
||||
menuBar.add( panel );
|
||||
menuBar.revalidate();
|
||||
}
|
||||
|
||||
private void removeMenu() {
|
||||
int menuCount = menuBar.getMenuCount();
|
||||
if( menuCount <= 0 )
|
||||
@@ -486,13 +535,31 @@ debug*/
|
||||
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_CLOSE, showCloseCheckBox.isSelected() ? null : false );
|
||||
}
|
||||
|
||||
private void fullWindowContentChanged() {
|
||||
JRootPane rootPane = getWindowRootPane();
|
||||
if( rootPane != null ) {
|
||||
boolean selected = fullWindowContentCheckBox.isSelected();
|
||||
rootPane.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT, selected ? true : null );
|
||||
|
||||
showIconCheckBox.setEnabled( !selected );
|
||||
showTitleCheckBox.setEnabled( !selected );
|
||||
}
|
||||
}
|
||||
|
||||
private JRootPane getWindowRootPane() {
|
||||
Window window = SwingUtilities.windowForComponent( this );
|
||||
if( window instanceof JFrame )
|
||||
return ((JFrame)window).getRootPane();
|
||||
else if( window instanceof JDialog )
|
||||
return ((JDialog)window).getRootPane();
|
||||
return null;
|
||||
return (window instanceof RootPaneContainer)
|
||||
? ((RootPaneContainer)window).getRootPane()
|
||||
: null;
|
||||
}
|
||||
|
||||
private void showRectangles() {
|
||||
JRootPane rootPane = getWindowRootPane();
|
||||
if( rootPane != null ) {
|
||||
UIManager.put( KEY_DEBUG_SHOW_RECTANGLES, showRectanglesCheckBox.isSelected() );
|
||||
rootPane.revalidate();
|
||||
rootPane.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
@@ -509,6 +576,9 @@ debug*/
|
||||
showIconifyCheckBox = new JCheckBox();
|
||||
showMaximizeCheckBox = new JCheckBox();
|
||||
showCloseCheckBox = new JCheckBox();
|
||||
fullWindowContentCheckBox = new JCheckBox();
|
||||
JLabel fullWindowContentButtonsBoundsLabel = new JLabel();
|
||||
fullWindowContentButtonsBoundsField = new JLabel();
|
||||
JPanel panel6 = new JPanel();
|
||||
menuBarCheckBox = new JCheckBox();
|
||||
menuBarEmbeddedCheckBox = new JCheckBox();
|
||||
@@ -519,6 +589,7 @@ debug*/
|
||||
addMenuButton = new JButton();
|
||||
addGlueButton = new JButton();
|
||||
addCaptionButton = new JButton();
|
||||
addTextFieldButton = new JButton();
|
||||
removeMenuButton = new JButton();
|
||||
changeMenuButton = new JButton();
|
||||
changeTitleButton = new JButton();
|
||||
@@ -543,11 +614,13 @@ debug*/
|
||||
colorizeTitleBarCheckBox = new JCheckBox();
|
||||
colorizeMenuBarCheckBox = new JCheckBox();
|
||||
colorizeMenusCheckBox = new JCheckBox();
|
||||
translucentWindowBackgroundCheckBox = new JCheckBox();
|
||||
JButton openDialogButton = new JButton();
|
||||
JButton openFrameButton = new JButton();
|
||||
typeNormalRadioButton = new JRadioButton();
|
||||
typeUtilityRadioButton = new JRadioButton();
|
||||
typeSmallRadioButton = new JRadioButton();
|
||||
showRectanglesCheckBox = new JCheckBox();
|
||||
menuBar = new JMenuBar();
|
||||
JMenu fileMenu = new JMenu();
|
||||
JMenuItem newMenuItem = new JMenuItem();
|
||||
@@ -586,6 +659,7 @@ debug*/
|
||||
// rows
|
||||
"[fill]" +
|
||||
"[fill]" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//======== panel7 ========
|
||||
@@ -643,6 +717,8 @@ debug*/
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]rel" +
|
||||
"[]rel" +
|
||||
"[]"));
|
||||
|
||||
//---- showIconCheckBox ----
|
||||
@@ -673,6 +749,19 @@ debug*/
|
||||
showCloseCheckBox.setSelected(true);
|
||||
showCloseCheckBox.addActionListener(e -> showCloseChanged());
|
||||
panel4.add(showCloseCheckBox, "cell 0 4");
|
||||
|
||||
//---- fullWindowContentCheckBox ----
|
||||
fullWindowContentCheckBox.setText("full window content");
|
||||
fullWindowContentCheckBox.addActionListener(e -> fullWindowContentChanged());
|
||||
panel4.add(fullWindowContentCheckBox, "cell 0 5");
|
||||
|
||||
//---- fullWindowContentButtonsBoundsLabel ----
|
||||
fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:");
|
||||
panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6");
|
||||
|
||||
//---- fullWindowContentButtonsBoundsField ----
|
||||
fullWindowContentButtonsBoundsField.setText("null");
|
||||
panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6");
|
||||
}
|
||||
add(panel4, "cell 1 0");
|
||||
|
||||
@@ -731,6 +820,7 @@ debug*/
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]unrel" +
|
||||
"[]"));
|
||||
|
||||
@@ -749,20 +839,25 @@ debug*/
|
||||
addCaptionButton.addActionListener(e -> addCaption());
|
||||
panel3.add(addCaptionButton, "cell 0 2");
|
||||
|
||||
//---- addTextFieldButton ----
|
||||
addTextFieldButton.setText("Add text field");
|
||||
addTextFieldButton.addActionListener(e -> addTextField());
|
||||
panel3.add(addTextFieldButton, "cell 0 3");
|
||||
|
||||
//---- removeMenuButton ----
|
||||
removeMenuButton.setText("Remove menu");
|
||||
removeMenuButton.addActionListener(e -> removeMenu());
|
||||
panel3.add(removeMenuButton, "cell 0 3");
|
||||
panel3.add(removeMenuButton, "cell 0 4");
|
||||
|
||||
//---- changeMenuButton ----
|
||||
changeMenuButton.setText("Change menu");
|
||||
changeMenuButton.addActionListener(e -> changeMenu());
|
||||
panel3.add(changeMenuButton, "cell 0 4");
|
||||
panel3.add(changeMenuButton, "cell 0 5");
|
||||
|
||||
//---- changeTitleButton ----
|
||||
changeTitleButton.setText("Change title");
|
||||
changeTitleButton.addActionListener(e -> changeTitle());
|
||||
panel3.add(changeTitleButton, "cell 0 5");
|
||||
panel3.add(changeTitleButton, "cell 0 6");
|
||||
}
|
||||
add(panel3, "cell 3 0 1 2,aligny top,growy 0");
|
||||
|
||||
@@ -885,6 +980,7 @@ debug*/
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]"));
|
||||
|
||||
//---- unifiedBackgroundCheckBox ----
|
||||
@@ -906,6 +1002,11 @@ debug*/
|
||||
colorizeMenusCheckBox.setText("colorize menus");
|
||||
colorizeMenusCheckBox.addActionListener(e -> colorizeMenus());
|
||||
panel5.add(colorizeMenusCheckBox, "cell 0 3");
|
||||
|
||||
//---- translucentWindowBackgroundCheckBox ----
|
||||
translucentWindowBackgroundCheckBox.setText("translucent window background");
|
||||
translucentWindowBackgroundCheckBox.addActionListener(e -> translucentWindowBackgroundChanged());
|
||||
panel5.add(translucentWindowBackgroundCheckBox, "cell 0 4");
|
||||
}
|
||||
add(panel5, "cell 2 1");
|
||||
|
||||
@@ -933,6 +1034,12 @@ debug*/
|
||||
typeSmallRadioButton.setText("Small");
|
||||
add(typeSmallRadioButton, "cell 0 2 3 1");
|
||||
|
||||
//---- showRectanglesCheckBox ----
|
||||
showRectanglesCheckBox.setText("Show debug title bar rectangles");
|
||||
showRectanglesCheckBox.setSelected(true);
|
||||
showRectanglesCheckBox.addActionListener(e -> showRectangles());
|
||||
add(showRectanglesCheckBox, "cell 0 3");
|
||||
|
||||
//======== menuBar ========
|
||||
{
|
||||
|
||||
@@ -1140,6 +1247,8 @@ debug*/
|
||||
private JCheckBox showIconifyCheckBox;
|
||||
private JCheckBox showMaximizeCheckBox;
|
||||
private JCheckBox showCloseCheckBox;
|
||||
private JCheckBox fullWindowContentCheckBox;
|
||||
private JLabel fullWindowContentButtonsBoundsField;
|
||||
private JCheckBox menuBarCheckBox;
|
||||
private JCheckBox menuBarEmbeddedCheckBox;
|
||||
private JCheckBox menuBarVisibleCheckBox;
|
||||
@@ -1148,6 +1257,7 @@ debug*/
|
||||
private JButton addMenuButton;
|
||||
private JButton addGlueButton;
|
||||
private JButton addCaptionButton;
|
||||
private JButton addTextFieldButton;
|
||||
private JButton removeMenuButton;
|
||||
private JButton changeMenuButton;
|
||||
private JButton changeTitleButton;
|
||||
@@ -1169,9 +1279,11 @@ debug*/
|
||||
private JCheckBox colorizeTitleBarCheckBox;
|
||||
private JCheckBox colorizeMenuBarCheckBox;
|
||||
private JCheckBox colorizeMenusCheckBox;
|
||||
private JCheckBox translucentWindowBackgroundCheckBox;
|
||||
private JRadioButton typeNormalRadioButton;
|
||||
private JRadioButton typeUtilityRadioButton;
|
||||
private JRadioButton typeSmallRadioButton;
|
||||
private JCheckBox showRectanglesCheckBox;
|
||||
private JMenuBar menuBar;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "8.2.1.0.348" Java: "21.0.1" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -9,7 +9,7 @@ new FormModel {
|
||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[left][fill][fill][fill]"
|
||||
"$rowConstraints": "[fill][fill][]"
|
||||
"$rowConstraints": "[fill][fill][][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
@@ -77,7 +77,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,hidemode 3,gap 0 0"
|
||||
"$columnConstraints": "[grow,left]"
|
||||
"$rowConstraints": "[][][][][]"
|
||||
"$rowConstraints": "[][][][][]rel[]rel[]"
|
||||
} ) {
|
||||
name: "panel4"
|
||||
"border": new javax.swing.border.TitledBorder( "Title Bar" )
|
||||
@@ -135,6 +135,31 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "fullWindowContentCheckBox"
|
||||
"text": "full window content"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullWindowContentChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fullWindowContentButtonsBoundsLabel"
|
||||
"text": "Buttons bounds:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fullWindowContentButtonsBoundsField"
|
||||
"text": "null"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
@@ -204,7 +229,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[fill]"
|
||||
"$rowConstraints": "[][][][][]unrel[]"
|
||||
"$rowConstraints": "[][][][][][]unrel[]"
|
||||
} ) {
|
||||
name: "panel3"
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
@@ -237,6 +262,16 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "addTextFieldButton"
|
||||
"text": "Add text field"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addTextField", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "removeMenuButton"
|
||||
"text": "Remove menu"
|
||||
@@ -245,7 +280,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "changeMenuButton"
|
||||
@@ -255,7 +290,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "changeTitleButton"
|
||||
@@ -265,7 +300,7 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 0 1 2,aligny top,growy 0"
|
||||
@@ -449,7 +484,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "ltr,hidemode 3,gap 0 0"
|
||||
"$columnConstraints": "[left]"
|
||||
"$rowConstraints": "[][][][]"
|
||||
"$rowConstraints": "[][][][]para[]"
|
||||
} ) {
|
||||
name: "panel5"
|
||||
"border": new javax.swing.border.TitledBorder( "Color" )
|
||||
@@ -493,6 +528,16 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "translucentWindowBackgroundCheckBox"
|
||||
"text": "translucent window background"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "translucentWindowBackgroundChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
@@ -542,6 +587,17 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showRectanglesCheckBox"
|
||||
"text": "Show debug title bar rectangles"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showRectangles", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 960, 495 )
|
||||
|
||||
@@ -119,10 +119,9 @@ public class UIDefaultsDump
|
||||
//
|
||||
// dump( "com.jgoodies.looks.plastic.PlasticLookAndFeel", dir, false );
|
||||
// dump( "com.jgoodies.looks.windows.WindowsLookAndFeel", dir, false );
|
||||
// dump( "com.alee.laf.WebLookAndFeel", dir, false );
|
||||
// try {
|
||||
// EventQueue.invokeAndWait( () -> {
|
||||
// dump( "org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel", dir, false );
|
||||
// SwingUtilities.invokeAndWait( () -> {
|
||||
// dump( "org.pushingpixels.radiance.theming.api.skin.RadianceGraphiteAquaLookAndFeel", dir, false );
|
||||
// } );
|
||||
// } catch( Exception ex ) {
|
||||
// // TODO Auto-generated catch block
|
||||
@@ -673,7 +672,7 @@ public class UIDefaultsDump
|
||||
|
||||
switch( borderClassName ) {
|
||||
case "com.apple.laf.AquaToolBarUI$ToolBarBorder":
|
||||
case "org.pushingpixels.substance.internal.utils.border.SubstanceToolBarBorder":
|
||||
case "org.pushingpixels.radiance.theming.internal.utils.border.RadianceToolBarBorder":
|
||||
c = new JToolBar();
|
||||
break;
|
||||
|
||||
|
||||
@@ -68,6 +68,20 @@ public class UIDefaultsKeysDump
|
||||
collectKeys( FlatDarculaLaf.class.getName(), keys );
|
||||
collectKeys( FlatTestLaf.class.getName(), keys );
|
||||
|
||||
// remove unused keys (defined in BasicLookAndFeel)
|
||||
keys.remove( "Button.textIconGap" );
|
||||
keys.remove( "Button.textShiftOffset" );
|
||||
keys.remove( "CheckBox.textIconGap" );
|
||||
keys.remove( "CheckBox.textShiftOffset" );
|
||||
keys.remove( "RadioButton.textIconGap" );
|
||||
keys.remove( "RadioButton.textShiftOffset" );
|
||||
keys.remove( "TabbedPane.contentOpaque" );
|
||||
keys.remove( "TabbedPane.selectedTabPadInsets" );
|
||||
keys.remove( "TabbedPane.shadow" );
|
||||
keys.remove( "TabbedPane.tabsOverlapBorder" );
|
||||
keys.remove( "ToggleButton.textIconGap" );
|
||||
keys.remove( "ToggleButton.textShiftOffset" );
|
||||
|
||||
// write key file
|
||||
try( Writer fileWriter = new BufferedWriter( new OutputStreamWriter(
|
||||
new FileOutputStream( keysFile ), StandardCharsets.UTF_8 ) ) )
|
||||
|
||||
@@ -64,8 +64,6 @@ Button.selectedForeground
|
||||
Button.shadow
|
||||
Button.startBackground
|
||||
Button.startBorderColor
|
||||
Button.textIconGap
|
||||
Button.textShiftOffset
|
||||
Button.toolbar.disabledSelectedBackground
|
||||
Button.toolbar.disabledSelectedForeground
|
||||
Button.toolbar.hoverBackground
|
||||
@@ -149,8 +147,6 @@ CheckBox.icon[filled].selectedBorderColor
|
||||
CheckBox.icon[filled].selectedBorderWidth
|
||||
CheckBox.margin
|
||||
CheckBox.rollover
|
||||
CheckBox.textIconGap
|
||||
CheckBox.textShiftOffset
|
||||
CheckBoxMenuItem.acceleratorForeground
|
||||
CheckBoxMenuItem.acceleratorSelectionForeground
|
||||
CheckBoxMenuItem.arrowIcon
|
||||
@@ -655,8 +651,6 @@ RadioButton.light
|
||||
RadioButton.margin
|
||||
RadioButton.rollover
|
||||
RadioButton.shadow
|
||||
RadioButton.textIconGap
|
||||
RadioButton.textShiftOffset
|
||||
RadioButtonMenuItem.acceleratorForeground
|
||||
RadioButtonMenuItem.acceleratorSelectionForeground
|
||||
RadioButtonMenuItem.arrowIcon
|
||||
@@ -855,7 +849,6 @@ TabbedPane.closePressedBackground
|
||||
TabbedPane.closePressedForeground
|
||||
TabbedPane.closeSize
|
||||
TabbedPane.contentAreaColor
|
||||
TabbedPane.contentOpaque
|
||||
TabbedPane.contentSeparatorHeight
|
||||
TabbedPane.darkShadow
|
||||
TabbedPane.disabledForeground
|
||||
@@ -881,9 +874,7 @@ TabbedPane.selectedBackground
|
||||
TabbedPane.selectedForeground
|
||||
TabbedPane.selectedInsets
|
||||
TabbedPane.selectedLabelShift
|
||||
TabbedPane.selectedTabPadInsets
|
||||
TabbedPane.selectionFollowsFocus
|
||||
TabbedPane.shadow
|
||||
TabbedPane.showTabSeparators
|
||||
TabbedPane.tabAlignment
|
||||
TabbedPane.tabArc
|
||||
@@ -901,7 +892,6 @@ TabbedPane.tabSeparatorsFullHeight
|
||||
TabbedPane.tabType
|
||||
TabbedPane.tabWidthMode
|
||||
TabbedPane.tabsOpaque
|
||||
TabbedPane.tabsOverlapBorder
|
||||
TabbedPane.tabsPopupPolicy
|
||||
TabbedPane.textIconGap
|
||||
TabbedPane.underlineColor
|
||||
@@ -920,6 +910,7 @@ Table.dropCellBackground
|
||||
Table.dropCellForeground
|
||||
Table.dropLineColor
|
||||
Table.dropLineShortColor
|
||||
Table.editorSelectAllOnStartEditing
|
||||
Table.focusCellBackground
|
||||
Table.focusCellForeground
|
||||
Table.focusCellHighlightBorder
|
||||
@@ -928,6 +919,7 @@ Table.font
|
||||
Table.foreground
|
||||
Table.gridColor
|
||||
Table.intercellSpacing
|
||||
Table.paintOutsideAlternateRows
|
||||
Table.rowHeight
|
||||
Table.scrollPaneBorder
|
||||
Table.selectionBackground
|
||||
@@ -1047,7 +1039,6 @@ TitlePane.inactiveBackground
|
||||
TitlePane.inactiveForeground
|
||||
TitlePane.maximizeIcon
|
||||
TitlePane.menuBarEmbedded
|
||||
TitlePane.menuBarResizeHeight
|
||||
TitlePane.menuBarTitleGap
|
||||
TitlePane.menuBarTitleMinimumGap
|
||||
TitlePane.noIconLeftGap
|
||||
@@ -1079,7 +1070,6 @@ TitlePane.small.iconifyIcon
|
||||
TitlePane.small.inactiveBackground
|
||||
TitlePane.small.inactiveForeground
|
||||
TitlePane.small.maximizeIcon
|
||||
TitlePane.small.menuBarResizeHeight
|
||||
TitlePane.small.menuBarTitleGap
|
||||
TitlePane.small.menuBarTitleMinimumGap
|
||||
TitlePane.small.noIconLeftGap
|
||||
@@ -1130,8 +1120,6 @@ ToggleButton.tab.selectedBackground
|
||||
ToggleButton.tab.selectedForeground
|
||||
ToggleButton.tab.underlineColor
|
||||
ToggleButton.tab.underlineHeight
|
||||
ToggleButton.textIconGap
|
||||
ToggleButton.textShiftOffset
|
||||
ToggleButton.toolbar.disabledSelectedBackground
|
||||
ToggleButton.toolbar.disabledSelectedForeground
|
||||
ToggleButton.toolbar.hoverBackground
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
flatlaf.releaseVersion = 3.3
|
||||
flatlaf.developmentVersion = 3.4-SNAPSHOT
|
||||
flatlaf.releaseVersion = 3.4
|
||||
flatlaf.developmentVersion = 3.5-SNAPSHOT
|
||||
|
||||
org.gradle.parallel = true
|
||||
# org.gradle.warning.mode = all
|
||||
|
||||
Reference in New Issue
Block a user