Compare commits

..

80 Commits

Author SHA1 Message Date
Karl Tauber
78a8035b92 Linux: rounded borders for popups (issue #949) 2025-01-27 17:15:38 +01:00
Karl Tauber
c32c00a5eb Linux with FlatLaf window decorations:
- moved window resizer components from layered pane to rootpane so that border is included in area where user can resize window
- scale border thickness
2025-01-26 17:48:19 +01:00
Karl Tauber
3a8a55a545 Linux with FlatLaf window decorations: right and bottom window resize drag areas were 2px smaller than at left and top sides 2025-01-26 17:23:59 +01:00
Karl Tauber
6c49b8bc4d Linux: hide popups when window is moved, resized, maximized, restored, iconified or switched to another window (issue #962) 2025-01-25 09:48:52 +01:00
Karl Tauber
cca9707f6b Popup: on Windows 10, update drop shadow of heavy-weight popup if popup moved/resized (issue #942) 2025-01-25 07:45:57 +01:00
Karl Tauber
f30dd876e4 Linux: updated libflatlaf-linux-arm64.so for Linux on ARM64; now built on ARM64 Linux (ubuntu-24.04-arm); previous was cross-compiled on X86_64 Linux (issue #899)
built by GitHub Actions: https://github.com/JFormDesigner/FlatLaf/actions/runs/12932258675
2025-01-23 16:38:16 +01:00
Karl Tauber
c6872d48b3 GitHub Actions:
- build Linux ARM64 native library on ubuntu-24.04-arm
- build on various Java versions only if build on Java 11 succeeded
- build Java version matrix only on main repo
2025-01-23 16:15:22 +01:00
Karl Tauber
5e78b21df7 macOS native rounded borders: (PR #772)
- removed opacity from contentView.layer
- catch and log exceptions
2025-01-21 11:59:40 +01:00
Karl Tauber
2ef87dc789 macOS: re-enabled rounded popup border (see PR #772) on macOS 14.4+ (was disabled in 3.5.x)
deferred rounded border setup, if popup window is not yet created, could make a difference (see commit 656d25b75e)
2025-01-20 19:42:55 +01:00
Karl Tauber
28904c34cc Linux: added libflatlaf-linux-arm64.so for Linux on ARM64 (issue #899)
built by GitHub Actions: https://github.com/JFormDesigner/FlatLaf/actions/runs/12845430366
2025-01-18 17:09:32 +01:00
Karl Tauber
91f19bf94c Native Libraries:
- Linux: added dumps
- macOS: replaced deprecated Gradle `exec`
2025-01-18 16:53:30 +01:00
Karl Tauber
0ea188f8db Linux: support cross-compile native library for ARM64 on x86_64 Linux (issue #899) 2025-01-18 14:50:42 +01:00
Karl Tauber
6c77b81277 Linux: support building native library for ARM64 when Gradle build runs on ARM64 Linux (issue #899) 2025-01-16 20:10:57 +01:00
Karl Tauber
ddee4ef526 GitHub Actions: natives.yml: install libxt-dev to fix build error on ubuntu 24.04 (did work without this on ubuntu 22.04) 2025-01-09 15:57:46 +01:00
Karl Tauber
f11f68282b update to Gradle 8.12 2025-01-09 15:39:27 +01:00
Karl Tauber
ac0cceb09b added Exocharts as Gold sponsor 2025-01-09 15:19:47 +01:00
Karl Tauber
a238fd4505 Button: fixed background and foreground colors for borderless and toolBarButton style default buttons (JButton.isDefaultButton() is true) (issue #947) 2025-01-09 14:38:36 +01:00
Karl Tauber
8dc6242889 FlatLaf window decorations: minimize and maximize icons were not shown for custom scale factors less than 100% (e.g. `-Dflatlaf.uiScale=75%) (issue #951) 2025-01-09 14:19:44 +01:00
Karl Tauber
d17fffb82a PopupFactory: fixed NPE on Windows 10 when owner is null (issue #952) 2025-01-09 12:26:57 +01:00
Karl Tauber
0ad3180b10 FileChooser: improved performance when navigating to large directories with thousands of files (issue #953) 2025-01-09 12:04:25 +01:00
Karl Tauber
80ba75fdeb List:
- fixed wrong x/width bounds of alternating rows for multi-column lists (PR #939)
- Demo: added "alternating rows" checkboxes to "Data Components" page
2024-12-18 12:22:04 +01:00
Karl Tauber
7027821c00 Merge PR #939: Support for alternate row color in JList 2024-12-18 00:30:01 +01:00
Karl Tauber
a3a49cef73 Merge PR #936: CheckBox: support styling indeterminate state of tri-state check boxes 2024-12-17 23:46:12 +01:00
Dar
abf77d5399 mod: code format 2024-12-16 15:55:40 +01:00
Dar
6404b8de2a fix: filter combobox by name 2024-12-16 15:49:19 +01:00
Dar
19055d5a18 mod: combobox does not support alternate row color 2024-12-13 09:21:14 +01:00
Dar
c12adf12e7 new: support for alternate row color in JList 2024-12-13 09:20:23 +01:00
Karl Tauber
b9c68fbe77 CheckBox: support styling indeterminate state of tri-state check boxes (issue #919) 2024-12-11 16:54:03 +01:00
Karl Tauber
7bdfd49921 Merge PR #935: Tree: support wide cell renderer 2024-12-11 13:33:03 +01:00
Karl Tauber
58fa2a5085 Demo, Testing, Theme Editor: re-generated UI code using JFormDesigner 8.3, which now supports class FlatClientProperties 2024-12-10 19:49:46 +01:00
Karl Tauber
a400799db5 Extras: use default activation keys if passing null to FlatInspector.install() or to FlatUIDefaultsInspector.install() 2024-12-09 23:55:02 +01:00
Karl Tauber
2a8e487c1f Tree: support wide cell renderer (issue #922) 2024-12-09 19:50:00 +01:00
Karl Tauber
145631fd43 FlatComponentsTest: added "transparent background" checkbox 2024-12-09 17:10:33 +01:00
Karl Tauber
6a774d8c70 GitHub Actions: use lftp directly to upload FlatLaf demo and theme editor
previously used github action `sebastianpopp/ftp-action`, which uses Docker, was very slow (about two minutes to upload one file)
2024-12-09 13:44:54 +01:00
Karl Tauber
bfd746f981 GitHub Actions: no longer upload theme editor snapshot; update gradle wrapper validation action 2024-12-09 01:23:55 +01:00
Karl Tauber
3af54b7215 Merge branch 'flatlaf-3.5.4' into main 2024-12-09 01:12:27 +01:00
Karl Tauber
3ba9fc6c1c release 3.5.4 2024-12-09 00:44:57 +01:00
Karl Tauber
0a9ecd66a9 Linux: fixed NPE when using FlatLaf window decorations and switching theme (issue #933; regression in 3.5.3)
caused by fix for #907; commit d471f08b15
2024-12-09 00:43:44 +01:00
Karl Tauber
6991d6729e Merge PR #931: Fixing NPE when using HTML text on a component with null font
(cherry picked from commit 41332de275)
2024-12-08 23:01:00 +01:00
Karl Tauber
304cb0d57b Merge PR #903: Support for alternate row color in JTree 2024-12-08 13:44:58 +01:00
Karl Tauber
41332de275 Merge PR #931: Fixing NPE when using HTML text on a component with null font 2024-12-08 13:37:02 +01:00
Karl Tauber
ef61ae504b FlatSVGIcon: color filters now can access painting component to implement component state based color mappings (PR #906) 2024-12-07 19:52:23 +01:00
Eduwardo Horibe
f96baf1bc2 Fixing NPE when using HTML text on a component with null font 2024-12-06 18:52:14 -03:00
Karl Tauber
1462636e97 release 3.5.3 2024-12-06 12:42:15 +01:00
Karl Tauber
7e59a7f4af FlatPropertiesLaf: support macOS themes as base themes 2024-12-04 23:56:01 +01:00
Karl Tauber
e9a21848bc ComboBox: do not paint arrow button background if it is hidden (issue #915) 2024-12-04 19:24:10 +01:00
Karl Tauber
1dcb251ecb FlatLaf window decorations: fixed sometimes broken window moving with SplitPane in window title area in "full window content" mode (issue #926) 2024-12-04 18:21:06 +01:00
Karl Tauber
3f33543cee Linux: fixed slightly different font size (or letter width) used to paint HTML text when default font family is _Cantarell_ (e.g. on Fedora) (issue #912)
the removed use of floating point font size is similar to what is done in JDK for GTK Look and Feel:
- https://bugs.openjdk.org/browse/JDK-6979979
- 306f12db9e
2024-12-04 17:18:33 +01:00
Karl Tauber
84bd2088f2 FlatSystemProperties: javadoc fixes 2024-12-04 13:06:37 +01:00
Karl Tauber
4f4a3132c5 UIScale:
- do not use "defaultFont" if current Laf is not FlatLaf
- support custom font size divider to calculate user scale factor from font size

(for special use in JFormDesigner)
2024-12-04 13:06:11 +01:00
Karl Tauber
e064c934cb Windows: fixed detection of Windows 11 if custom exe launcher does not specify Windows 10+ compatibility in application manifest (issue #916)
Windows binaries built and signed locally in clean workspace
2024-11-28 14:12:56 +01:00
Karl Tauber
16fc3cabf2 Popup: fixed NPE if GraphicsConfiguration is null on Windows (issue #921)
also check for null GraphicsConfiguration in other classes
2024-11-27 19:27:47 +01:00
Karl Tauber
7e002ff6c2 Theme Editor: fixed using color picker on secondary screen 2024-11-27 19:02:13 +01:00
Karl Tauber
323c0c62c3 update to Gradle 8.11.1 2024-11-20 20:11:34 +01:00
Karl Tauber
ff5bd301cc Popup: on Windows 10, fixed misplaced popup drop shadow (issue #911; regression in 3.5 since commit a311bac89b) 2024-11-19 23:25:50 +01:00
Karl Tauber
c37712b0f0 Windows: fixed wrong layout in maximized frame after changing screen scale factor (issue #904)
Windows binaries built and signed locally in clean workspace
2024-11-17 19:41:54 +01:00
Karl Tauber
ee9e238592 Windows: fixed possible deadlock with TabbedPane in window title area in "full window content" mode (issue #909) 2024-11-14 19:34:31 +01:00
Karl Tauber
da5d6fa157 update to Gradle 8.11 2024-11-14 18:39:37 +01:00
Karl Tauber
d471f08b15 Linux: fixed continuous cursor toggling between resize and standard cursor when resizing window with FlatLaf window decorations (issue #907) 2024-11-14 18:34:55 +01:00
Karl Tauber
b97424f767 HTML: fixed wrong rendering if HTML text contains <style> tag with attributes (e.g. <style type='text/css'>) (issue #905; regression in 3.5) 2024-11-10 13:28:02 +01:00
Dar
a20cfa6db3 mod: style tester 2024-10-23 15:36:17 +02:00
Dar
6ac6698ecf mod: added 3.6 tag 2024-10-23 15:32:16 +02:00
Dar
8004d2761a fix: respect the selection arc 2024-10-23 15:30:06 +02:00
Dar
25c2bbc851 fix: alternate row color paint 2024-10-22 18:05:14 +02:00
Dar
33e37a7167 new: support for alternate row color in jtree
see: https://github.com/JFormDesigner/FlatLaf/issues/900
2024-10-22 16:46:30 +02:00
Karl Tauber
c29a276188 release 3.5.2 2024-10-18 13:28:53 +02:00
Karl Tauber
d1694aa8bd FlatClientProperties and FlatSystemProperties: javadoc fixes 2024-10-18 13:28:07 +02:00
Karl Tauber
570cf6fc51 FlatLaf window decorations: added client property JRootPane.titleBarHeight to allow specifying a (larger) preferred height for the title bar (issue #897) 2024-10-17 19:58:58 +02:00
Karl Tauber
8eab86e489 FlatLaf window decorations: strech iconify/maximize/close buttons to always fill whole title bar height (issue #897) 2024-10-17 19:49:51 +02:00
Karl Tauber
566568f61a Windows: fixed repaint issues (ghosting) on some systems by setting sun.java2d.d3d.onscreen to false (issue #887) 2024-10-17 13:19:04 +02:00
Karl Tauber
56a73a4d17 Popup: added system property flatlaf.useRoundedPopupBorder to allow disabling native rounded popup borders (PRs #643 and #772) 2024-10-15 00:29:15 +02:00
Karl Tauber
656d25b75e Popup: setup rounded popup border after window was created (no longer create window ourself using addNotify()) to (hopefully) fix repaint issues on some Windows 11 systems after first showing a popup (issue #887, PR #643) 2024-10-12 23:25:59 +02:00
Karl Tauber
dcdc80ade3 Testing: FlatOptionPaneTest: test option pane with custom title bar icon (issue #886) 2024-10-12 00:28:19 +02:00
Karl Tauber
09f2d65d5e change snapshot version from 3.6-SNAPSHOT to 3.5.2-SNAPSHOT 2024-10-11 19:27:23 +02:00
Karl Tauber
b304d46f7e TextComponents: fixed too fast scrolling in multi-line text components when using touchpads (e.g. on macOS) (issue #892) 2024-10-11 19:18:00 +02:00
Karl Tauber
3391f971ec GitHub Actions: build using Java 23 2024-10-11 15:16:49 +02:00
Karl Tauber
778fed27a5 update to Gradle 8.10.2 2024-10-11 15:14:11 +02:00
Karl Tauber
1755dbc877 README.md updated 2024-10-11 15:11:56 +02:00
Karl Tauber
4e6f538519 ToolBar: fixed endless loop if button in Toolbar has focus and is made invisible (issue #884) 2024-09-29 19:26:37 +02:00
Karl Tauber
a6ecb0ef85 FlatLaf window decorations on Windows: fixed possible application freeze when using custom component that overrides Component.contains(int x, int y) and invokes SwingUtilities.convertPoint() (or similar) from the overridden method (issue #878) 2024-09-04 00:48:42 +02:00
116 changed files with 3164 additions and 747 deletions

View File

@@ -20,47 +20,29 @@ on:
jobs: jobs:
build: build:
name: build (11)
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
# test against
# - Java 8 (minimum requirement)
# - Java LTS versions (11, 17, ...)
# - latest Java version(s)
java:
- 8
- 11 # LTS
- 17 # LTS
- 21 # LTS
toolchain: [""]
include:
- java: 21
toolchain: 22 # latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2 - uses: gradle/actions/wrapper-validation@v4
if: matrix.java == '8'
- name: Setup Java ${{ matrix.java }} - name: Setup Java 11
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
java-version: ${{ matrix.java }} java-version: 11
distribution: temurin # Java 8, 11, 17 and 21 are pre-installed on ubuntu-latest distribution: temurin # pre-installed on ubuntu-latest
cache: gradle cache: gradle
- name: Check with Error Prone - name: Check with Error Prone
if: matrix.java == '11' run: ./gradlew errorprone clean
run: ./gradlew errorprone clean -Dtoolchain=${{ matrix.toolchain }}
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }} run: ./gradlew build
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: matrix.java == '11'
with: with:
name: FlatLaf-build-artifacts name: FlatLaf-build-artifacts
path: | path: |
@@ -70,9 +52,44 @@ jobs:
!**/*-sources.jar !**/*-sources.jar
snapshot: build-on:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: github.repository == 'JFormDesigner/FlatLaf'
strategy:
matrix:
# test against
# - Java 8 (minimum requirement)
# - Java LTS versions (11, 17, ...)
# - latest Java version(s)
java:
- 8
- 17 # LTS
- 21 # LTS
- 23 # latest
toolchain: [""]
# include:
# - java: 21
# toolchain: 22 # latest
steps:
- uses: actions/checkout@v4
- name: Setup Java ${{ matrix.java }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: temurin # Java 8, 11, 17 and 21 are pre-installed on ubuntu-latest
cache: gradle
- name: Build with Gradle
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
snapshot:
runs-on: ubuntu-latest
needs: build-on
if: | if: |
github.event_name == 'push' && github.event_name == 'push' &&
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) && (github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
@@ -89,26 +106,15 @@ jobs:
cache: gradle cache: gradle
- name: Publish snapshot to oss.sonatype.org - name: Publish snapshot to oss.sonatype.org
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false run: ./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
env: env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
- name: Upload theme editor
uses: sebastianpopp/ftp-action@releases/v2
with:
host: ${{ secrets.FTP_SERVER }}
user: ${{ secrets.FTP_USERNAME }}
password: ${{ secrets.FTP_PASSWORD }}
forceSsl: true
localDir: "flatlaf-theme-editor/build/libs"
remoteDir: "snapshots"
options: "--only-newer --no-recursion --verbose=1"
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build-on
if: | if: |
github.event_name == 'push' && github.event_name == 'push' &&
startsWith( github.ref, 'refs/tags/' ) && startsWith( github.ref, 'refs/tags/' ) &&
@@ -132,24 +138,12 @@ jobs:
SIGNING_KEY: ${{ secrets.SIGNING_KEY }} SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
- name: Upload demo - name: Install lftp
uses: sebastianpopp/ftp-action@releases/v2 run: sudo apt-get -y install lftp
with:
host: ${{ secrets.FTP_SERVER }}
user: ${{ secrets.FTP_USERNAME }}
password: ${{ secrets.FTP_PASSWORD }}
forceSsl: true
localDir: "flatlaf-demo/build/libs"
remoteDir: "."
options: "--only-newer --no-recursion --verbose=1"
- name: Upload theme editor - name: Upload demo and theme editor
uses: sebastianpopp/ftp-action@releases/v2 run: >
with: lftp -c "set ftp:ssl-force true;
host: ${{ secrets.FTP_SERVER }} open -u ${{ secrets.FTP_USERNAME }},${{ secrets.FTP_PASSWORD }} ${{ secrets.FTP_SERVER }};
user: ${{ secrets.FTP_USERNAME }} mput flatlaf-demo/build/libs/flatlaf-demo-*.jar;
password: ${{ secrets.FTP_PASSWORD }} mput flatlaf-theme-editor/build/libs/flatlaf-theme-editor-*.jar"
forceSsl: true
localDir: "flatlaf-theme-editor/build/libs"
remoteDir: "."
options: "--only-newer --no-recursion --verbose=1"

View File

@@ -21,16 +21,25 @@ jobs:
strategy: strategy:
matrix: matrix:
os: os:
- windows - windows-latest
- macos - macos-latest
- ubuntu - ubuntu-latest
- ubuntu-24.04-arm
runs-on: ${{ matrix.os }}-latest runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2 - uses: gradle/actions/wrapper-validation@v4
- name: install libxt-dev
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
run: sudo apt install libxt-dev
- name: install g++-aarch64-linux-gnu
if: matrix.os == 'ubuntu-latest'
run: sudo apt install g++-aarch64-linux-gnu
- name: Setup Java 11 - name: Setup Java 11
uses: actions/setup-java@v4 uses: actions/setup-java@v4

View File

@@ -1,6 +1,112 @@
FlatLaf Change Log FlatLaf Change Log
================== ==================
## 3.6-SNAPSHOT
#### New features and improvements
- macOS: Re-enabled rounded popup border (see PR #772) on macOS 14.4+ (was
disabled in 3.5.x).
- CheckBox: Support styling indeterminate state of
[tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html).
(PR #936; issue #919)
- List: Support for alternate row highlighting. (PR #939)
- Tree: Support for alternate row highlighting. (PR #903)
- Tree: Support wide cell renderer. (issue #922)
- Extras: `FlatSVGIcon` color filters now can access painting component to
implement component state based color mappings. (issue #906)
- Linux: Added `libflatlaf-linux-arm64.so` for Linux on ARM64. (issue #899)
#### Fixed bugs
- Button: Fixed background and foreground colors for `borderless` and
`toolBarButton` style default buttons (`JButton.isDefaultButton()` is `true`).
(issue #947)
- FileChooser: Improved performance when navigating to large directories with
thousands of files. (issue #953)
- PopupFactory: Fixed NPE on Windows 10 when `owner` is `null`. (issue #952)
- Popup: On Windows 10, drop shadow of heavy-weight popup was not updated if
popup moved/resized. (issue #942)
- FlatLaf window decorations: Minimize and maximize icons were not shown for
custom scale factors less than 100% (e.g. `-Dflatlaf.uiScale=75%`). (issue
#951)
- Linux: Popups (menus and combobox lists) were not hidden when window is moved,
resized, maximized, restored, iconified or switched to another window. (issue
#962)
## 3.5.4
#### Fixed bugs
- HTML: Fixed NPE when using HTML text on a component with `null` font. (issue
#930; PR #931; regression in 3.5)
- Linux: Fixed NPE when using FlatLaf window decorations and switching theme.
(issue #933; regression in 3.5.3)
## 3.5.3
#### Fixed bugs
- HTML: Fixed wrong rendering if HTML text contains `<style>` tag with
attributes (e.g. `<style type='text/css'>`). (issue #905; regression in 3.5.1)
- FlatLaf window decorations:
- Windows: Fixed possible deadlock with TabbedPane in window title area in
"full window content" mode. (issue #909)
- Windows: Fixed wrong layout in maximized frame after changing screen scale
factor. (issue #904)
- Linux: Fixed continuous cursor toggling between resize and standard cursor
when resizing window. (issue #907)
- Fixed sometimes broken window moving with SplitPane in window title area in
"full window content" mode. (issue #926)
- Popup: On Windows 10, fixed misplaced popup drop shadow. (issue #911;
regression in 3.5)
- Popup: Fixed NPE if `GraphicsConfiguration` is `null` on Windows. (issue #921)
- Theme Editor: Fixed using color picker on secondary screen.
- Fixed detection of Windows 11 if custom exe launcher does not specify Windows
10+ compatibility in application manifest. (issue #916)
- Linux: Fixed slightly different font size (or letter width) used to paint HTML
text when default font family is _Cantarell_ (e.g. on Fedora). (issue #912)
#### Other Changes
- Class `FlatPropertiesLaf` now supports FlatLaf macOS themes as base themes.
## 3.5.2
#### Fixed bugs
- Windows: Fixed repaint issues (ghosting) on some systems (probably depending
on graphics card/driver). This is done by setting Java system property
`sun.java2d.d3d.onscreen` to `false` (but only if `sun.java2d.d3d.onscreen`,
`sun.java2d.d3d` and `sun.java2d.noddraw` are not yet set), which disables
usage of Windows Direct3D (DirectX) onscreen surfaces. Component rendering
still uses Direct3D. (issue #887)
- FlatLaf window decorations:
- Iconify/maximize/close buttons did not fill whole title bar height, if some
custom component in menu bar increases title bar height. (issue #897)
- Windows: Fixed possible application freeze when using custom component that
overrides `Component.contains(int x, int y)` and invokes
`SwingUtilities.convertPoint()` (or similar) from the overridden method.
(issue #878)
- TextComponents: Fixed too fast scrolling in multi-line text components when
using touchpads (e.g. on macOS). (issue #892)
- ToolBar: Fixed endless loop if button in Toolbar has focus and is made
invisible. (issue #884)
#### Other Changes
- FlatLaf window decorations: Added client property `JRootPane.titleBarHeight`
to allow specifying a (larger) preferred height for the title bar. (issue
#897)
- Added system property `flatlaf.useRoundedPopupBorder` to allow disabling
native rounded popup borders on Windows 11 and macOS. On macOS 14.4+, where
rounded popup borders are disabled since FlatLaf 3.5 because of occasional
problems, you can use this to enable rounded popup borders (at your risk).
## 3.5.1 ## 3.5.1
#### Fixed bugs #### Fixed bugs

View File

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

View File

@@ -156,5 +156,6 @@ flatlafPublish {
NativeArtifact( "${natives}/libflatlaf-macos-arm64.dylib", "macos-arm64", "dylib" ), NativeArtifact( "${natives}/libflatlaf-macos-arm64.dylib", "macos-arm64", "dylib" ),
NativeArtifact( "${natives}/libflatlaf-macos-x86_64.dylib", "macos-x86_64", "dylib" ), NativeArtifact( "${natives}/libflatlaf-macos-x86_64.dylib", "macos-x86_64", "dylib" ),
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ), NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
NativeArtifact( "${natives}/libflatlaf-linux-arm64.so", "linux-arm64", "so" ),
) )
} }

View File

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

View File

@@ -384,6 +384,7 @@ public interface FlatClientProperties
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used. * If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used. * If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
* <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported. * <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported.
* <li><strong>Linux</strong> (since FlatLaf 3.6): Any corner radius is supported.
* </ul> * </ul>
* <strong>Component</strong> {@link javax.swing.JComponent}<br> * <strong>Component</strong> {@link javax.swing.JComponent}<br>
* <strong>Value type</strong> {@link java.lang.Integer}<br> * <strong>Value type</strong> {@link java.lang.Integer}<br>
@@ -402,6 +403,7 @@ public interface FlatClientProperties
* Supported platforms: * Supported platforms:
* <ul> * <ul>
* <li><strong>macOS</strong> (10.14 and later) * <li><strong>macOS</strong> (10.14 and later)
* <li><strong>Linux</strong> (since FlatLaf 3.6)
* </ul> * </ul>
* <strong>Component</strong> {@link javax.swing.JComponent}<br> * <strong>Component</strong> {@link javax.swing.JComponent}<br>
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br> * <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br>
@@ -461,7 +463,7 @@ public interface FlatClientProperties
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority * {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
* than UI default {@code TitlePane.useWindowDecorations}. * than UI default {@code TitlePane.useWindowDecorations}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -481,7 +483,7 @@ public interface FlatClientProperties
* {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority * {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority
* than UI default {@code TitlePane.menuBarEmbedded}. * than UI default {@code TitlePane.menuBarEmbedded}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -507,6 +509,8 @@ public interface FlatClientProperties
* The user can left-click-and-drag on the title bar area to move the window, * The user can left-click-and-drag on the title bar area to move the window,
* except when clicking on a component that processes mouse events (e.g. buttons or menus). * except when clicking on a component that processes mouse events (e.g. buttons or menus).
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -537,7 +541,7 @@ public interface FlatClientProperties
* <p> * <p>
* This client property has higher priority than UI default {@code TitlePane.showIcon}. * This client property has higher priority than UI default {@code TitlePane.showIcon}.
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
@@ -553,6 +557,8 @@ public interface FlatClientProperties
* Setting this shows/hides the windows title * Setting this shows/hides the windows title
* for the {@code JFrame} or {@code JDialog} that contains the root pane. * for the {@code JFrame} or {@code JDialog} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -567,6 +573,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "iconify" button * Setting this shows/hides the "iconify" button
* for the {@code JFrame} that contains the root pane. * for the {@code JFrame} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -581,6 +589,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "maximize/restore" button * Setting this shows/hides the "maximize/restore" button
* for the {@code JFrame} that contains the root pane. * for the {@code JFrame} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -595,6 +605,8 @@ public interface FlatClientProperties
* Setting this shows/hides the "close" button * Setting this shows/hides the "close" button
* for the {@code JFrame} or {@code JDialog} that contains the root pane. * for the {@code JFrame} or {@code JDialog} that contains the root pane.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -605,7 +617,7 @@ public interface FlatClientProperties
/** /**
* Background color of window title bar (requires enabled window decorations). * Background color of window title bar (requires enabled window decorations).
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color} * <strong>Value type</strong> {@link java.awt.Color}
@@ -617,7 +629,7 @@ public interface FlatClientProperties
/** /**
* Foreground color of window title bar (requires enabled window decorations). * Foreground color of window title bar (requires enabled window decorations).
* <p> * <p>
* (requires Window 10) * (requires Windows 10/11)
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.awt.Color} * <strong>Value type</strong> {@link java.awt.Color}
@@ -626,10 +638,24 @@ public interface FlatClientProperties
*/ */
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"; String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
/**
* Specifies the preferred height of title bar (requires enabled window decorations).
* <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Integer}
*
* @since 3.5.2
*/
String TITLE_BAR_HEIGHT = "JRootPane.titleBarHeight";
/** /**
* Specifies whether the glass pane should have full height and overlap the title bar, * Specifies whether the glass pane should have full height and overlap the title bar,
* if FlatLaf window decorations are enabled. Default is {@code false}. * if FlatLaf window decorations are enabled. Default is {@code false}.
* <p> * <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br> * <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
* *
@@ -1386,13 +1412,23 @@ public interface FlatClientProperties
//---- JTree -------------------------------------------------------------- //---- JTree --------------------------------------------------------------
/** /**
* Override if a tree shows a wide selection. Default is {@code true}. * Specifies whether tree shows a wide selection. Default is {@code true}.
* <p> * <p>
* <strong>Component</strong> {@link javax.swing.JTree}<br> * <strong>Component</strong> {@link javax.swing.JTree}<br>
* <strong>Value type</strong> {@link java.lang.Boolean} * <strong>Value type</strong> {@link java.lang.Boolean}
*/ */
String TREE_WIDE_SELECTION = "JTree.wideSelection"; String TREE_WIDE_SELECTION = "JTree.wideSelection";
/**
* Specifies whether tree uses a wide cell renderer. Default is {@code false}.
* <p>
* <strong>Component</strong> {@link javax.swing.JTree}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @since 3.6
*/
String TREE_WIDE_CELL_RENDERER = "JTree.wideCellRenderer";
/** /**
* Specifies whether tree item selection is painted. Default is {@code true}. * Specifies whether tree item selection is painted. Default is {@code true}.
* If set to {@code false}, then the tree cell renderer is responsible for painting selection. * If set to {@code false}, then the tree cell renderer is responsible for painting selection.

View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Image; import java.awt.Image;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.Toolkit; import java.awt.Toolkit;
@@ -110,6 +111,7 @@ public abstract class FlatLaf
private PopupFactory oldPopupFactory; private PopupFactory oldPopupFactory;
private MnemonicHandler mnemonicHandler; private MnemonicHandler mnemonicHandler;
private boolean subMenuUsabilityHelperInstalled; private boolean subMenuUsabilityHelperInstalled;
private LinuxPopupMenuCanceler linuxPopupMenuCanceler;
private Consumer<UIDefaults> postInitialization; private Consumer<UIDefaults> postInitialization;
private List<Function<Object, Object>> uiDefaultsGetters; private List<Function<Object, Object>> uiDefaultsGetters;
@@ -119,6 +121,46 @@ public abstract class FlatLaf
private static String preferredSemiboldFontFamily; private static String preferredSemiboldFontFamily;
private static String preferredMonospacedFontFamily; private static String preferredMonospacedFontFamily;
static {
// see disableWindowsD3Donscreen() for details
// https://github.com/JFormDesigner/FlatLaf/issues/887
if( SystemInfo.isWindows &&
System.getProperty( "sun.java2d.d3d.onscreen" ) == null &&
System.getProperty( "sun.java2d.d3d" ) == null &&
System.getProperty( "sun.java2d.noddraw" ) == null )
System.setProperty( "sun.java2d.d3d.onscreen", "false" );
}
/**
* Disable usage of Windows Direct3D (DirectX) onscreen surfaces because this may lead to
* repaint issues (ghosting) on some systems (probably depending on graphics card/driver).
* Problem occurs usually when a small heavy-weight popup window (menu, combobox, tooltip) is shown.
* <p>
* Sets system property {@code sun.java2d.d3d.onscreen} to {@code false},
* but only if {@code sun.java2d.d3d.onscreen}, {@code sun.java2d.d3d}
* and {@code sun.java2d.noddraw} are not yet set.
* <p>
* <strong>Note</strong>: Must be invoked very early before the graphics environment is created.
* <p>
* This method is automatically invoked when loading this class,
* which is usually before the graphics environment is created.
* E.g. when doing {@code FlatLightLaf.setup()} or
* {@code UIManager.setLookAndFeel( "com.formdev.flatlaf.FlatLightLaf" )}.
* <p>
* However, it may be invoked too late if you use some methods from {@link UIManager}
* of {@link GraphicsEnvironment} before setting look and feel.
* E.g. {@link UIManager#put(Object, Object)}.
* In that case invoke this method yourself very early.
* <p>
* <strong>Tip</strong>: How to find out when the graphics environment is created?
* Set a breakpoint at constructor of class {@link GraphicsEnvironment} and look at the stack.
*
* @since 3.5.2
*/
public static void disableWindowsD3Donscreen() {
// dummy method used to trigger invocation of "static {...}" block
}
/** /**
* Sets the application look and feel to the given LaF * Sets the application look and feel to the given LaF
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}. * using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
@@ -264,6 +306,10 @@ public abstract class FlatLaf
// install submenu usability helper // install submenu usability helper
subMenuUsabilityHelperInstalled = SubMenuUsabilityHelper.install(); subMenuUsabilityHelperInstalled = SubMenuUsabilityHelper.install();
// install Linux popup menu canceler
if( SystemInfo.isLinux )
linuxPopupMenuCanceler = new LinuxPopupMenuCanceler();
// listen to desktop property changes to update UI if system font or scaling changes // listen to desktop property changes to update UI if system font or scaling changes
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
// Windows 10 allows increasing font size independent of scaling: // Windows 10 allows increasing font size independent of scaling:
@@ -356,6 +402,12 @@ public abstract class FlatLaf
subMenuUsabilityHelperInstalled = false; subMenuUsabilityHelperInstalled = false;
} }
// uninstall Linux popup menu canceler
if( linuxPopupMenuCanceler != null ) {
linuxPopupMenuCanceler.uninstall();
linuxPopupMenuCanceler = null;
}
// restore default link color // restore default link color
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" ); new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
postInitialization = null; postInitialization = null;

View File

@@ -23,13 +23,15 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.Properties; import java.util.Properties;
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
import com.formdev.flatlaf.themes.FlatMacLightLaf;
/** /**
* A Flat LaF that is able to load UI defaults from properties passed to the constructor. * A Flat LaF that is able to load UI defaults from properties passed to the constructor.
* <p> * <p>
* Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}. * Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}.
* Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark}, * Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark},
* {@code intellij} or {@code darcula}. * {@code intellij}, {@code darcula}, {@code maclight} or {@code macdark}.
* <p> * <p>
* The properties are applied after loading the base theme and may overwrite base properties. * The properties are applied after loading the base theme and may overwrite base properties.
* All features of FlatLaf properties files are available. * All features of FlatLaf properties files are available.
@@ -71,7 +73,8 @@ public class FlatPropertiesLaf
this.properties = properties; this.properties = properties;
baseTheme = properties.getProperty( "@baseTheme", "light" ); baseTheme = properties.getProperty( "@baseTheme", "light" );
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme ); dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme ) ||
"macdark".equalsIgnoreCase( baseTheme );
} }
@Override @Override
@@ -116,6 +119,16 @@ public class FlatPropertiesLaf
lafClasses.add( FlatDarkLaf.class ); lafClasses.add( FlatDarkLaf.class );
lafClasses.add( FlatDarculaLaf.class ); lafClasses.add( FlatDarculaLaf.class );
break; break;
case "maclight":
lafClasses.add( FlatLightLaf.class );
lafClasses.add( FlatMacLightLaf.class );
break;
case "macdark":
lafClasses.add( FlatDarkLaf.class );
lafClasses.add( FlatMacDarkLaf.class );
break;
} }
return lafClasses; return lafClasses;
} }

View File

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

View File

@@ -111,7 +111,7 @@ class LinuxFontPolicy
if( logicalFamily != null ) if( logicalFamily != null )
family = logicalFamily; family = logicalFamily;
return createFontEx( family, style, size, dsize ); return createFontEx( family, style, size );
} }
/** /**
@@ -121,9 +121,9 @@ class LinuxFontPolicy
* E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found. * E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found.
* If still not found, then font of family 'Dialog' is returned. * If still not found, then font of family 'Dialog' is returned.
*/ */
private static Font createFontEx( String family, int style, int size, double dsize ) { private static Font createFontEx( String family, int style, int size ) {
for(;;) { for(;;) {
Font font = createFont( family, style, size, dsize ); Font font = FlatLaf.createCompositeFont( family, style, size );
if( Font.DIALOG.equals( family ) ) if( Font.DIALOG.equals( family ) )
return font; return font;
@@ -135,7 +135,7 @@ class LinuxFontPolicy
// - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8) // - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8)
FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font ); FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font );
if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 ) if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 )
return createFont( Font.DIALOG, style, size, dsize ); return FlatLaf.createCompositeFont( Font.DIALOG, style, size );
return font; return font;
} }
@@ -143,7 +143,7 @@ class LinuxFontPolicy
// find last word in family // find last word in family
int index = family.lastIndexOf( ' ' ); int index = family.lastIndexOf( ' ' );
if( index < 0 ) if( index < 0 )
return createFont( Font.DIALOG, style, size, dsize ); return FlatLaf.createCompositeFont( Font.DIALOG, style, size );
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy) // check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH ); String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH );
@@ -155,15 +155,6 @@ class LinuxFontPolicy
} }
} }
private static Font createFont( String family, int style, int size, double dsize ) {
Font font = FlatLaf.createCompositeFont( family, style, size );
// set font size in floating points
font = font.deriveFont( style, (float) dsize );
return font;
}
private static double getGnomeFontScale() { private static double getGnomeFontScale() {
// do not scale font here if JRE scales // do not scale font here if JRE scales
if( isSystemScaling() ) if( isSystemScaling() )
@@ -257,7 +248,7 @@ class LinuxFontPolicy
if( size < 1 ) if( size < 1 )
size = 1; size = 1;
return createFont( family, style, size, dsize ); return FlatLaf.createCompositeFont( family, style, size );
} }
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone @SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2025 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;
import java.awt.Component;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Cancels (hides) popup menus on Linux.
* <p>
* On Linux, popups are not hidden under following conditions, which results in
* misplaced popups:
* <ul>
* <li>window moved or resized
* <li>window maximized or restored
* <li>window iconified
* <li>window deactivated (e.g. activated other application)
* </ul>
*
* On Windows and macOS, popups are automatically hidden.
* <p>
* The implementation is similar to what's done in
* {@code javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber},
* but only hides popup in some conditions.
*
* @author Karl Tauber
*/
class LinuxPopupMenuCanceler
extends WindowAdapter
implements ChangeListener, ComponentListener
{
private MenuElement[] lastPathSelectedPath;
private Window window;
LinuxPopupMenuCanceler() {
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
msm.addChangeListener( this );
lastPathSelectedPath = msm.getSelectedPath();
if( lastPathSelectedPath.length > 0 )
addWindowListeners( lastPathSelectedPath[0] );
}
void uninstall() {
MenuSelectionManager.defaultManager().removeChangeListener( this );
}
private void addWindowListeners( MenuElement selected ) {
// see BasicPopupMenuUI.MouseGrabber.grabWindow()
Component invoker = selected.getComponent();
if( invoker instanceof JPopupMenu )
invoker = ((JPopupMenu)invoker).getInvoker();
window = (invoker instanceof Window)
? (Window) invoker
: SwingUtilities.windowForComponent( invoker );
if( window != null ) {
window.addWindowListener( this );
window.addComponentListener( this );
}
}
private void removeWindowListeners() {
if( window != null ) {
window.removeWindowListener( this );
window.removeComponentListener( this );
window = null;
}
}
private void cancelPopupMenu() {
try {
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
MenuElement[] selectedPath = msm.getSelectedPath();
for( MenuElement e : selectedPath ) {
if( e instanceof JPopupMenu )
((JPopupMenu)e).putClientProperty( "JPopupMenu.firePopupMenuCanceled", true );
}
msm.clearSelectedPath();
} catch( RuntimeException ex ) {
removeWindowListeners();
throw ex;
} catch( Error ex ) {
removeWindowListeners();
throw ex;
}
}
//---- ChangeListener ----
@Override
public void stateChanged( ChangeEvent e ) {
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
if( selectedPath.length == 0 )
removeWindowListeners();
else if( lastPathSelectedPath.length == 0 )
addWindowListeners( selectedPath[0] );
lastPathSelectedPath = selectedPath;
}
//---- WindowListener ----
@Override
public void windowIconified( WindowEvent e ) {
cancelPopupMenu();
}
@Override
public void windowDeactivated( WindowEvent e ) {
cancelPopupMenu();
}
@Override
public void windowClosing( WindowEvent e ) {
cancelPopupMenu();
}
//---- ComponentListener ----
@Override
public void componentResized( ComponentEvent e ) {
cancelPopupMenu();
}
@Override
public void componentMoved( ComponentEvent e ) {
cancelPopupMenu();
}
@Override
public void componentShown( ComponentEvent e ) {
}
@Override
public void componentHidden( ComponentEvent e ) {
cancelPopupMenu();
}
}

View File

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

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.icons; package com.formdev.flatlaf.icons;
import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.FlatClientProperties.*;
import static com.formdev.flatlaf.ui.FlatUIUtils.stateColor;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
@@ -48,6 +49,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
* @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth * @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth
* @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth * @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth
* @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth * @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
* @uiDefault CheckBox.icon.indeterminateBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
* @uiDefault CheckBox.icon.disabledIndeterminateBorderWidth int or float optional; defaults to CheckBox.icon.disabledSelectedBorderWidth
* @uiDefault CheckBox.arc int * @uiDefault CheckBox.arc int
* *
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor * @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
@@ -56,30 +59,45 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
* @uiDefault CheckBox.icon.selectedBorderColor Color * @uiDefault CheckBox.icon.selectedBorderColor Color
* @uiDefault CheckBox.icon.selectedBackground Color * @uiDefault CheckBox.icon.selectedBackground Color
* @uiDefault CheckBox.icon.checkmarkColor Color * @uiDefault CheckBox.icon.checkmarkColor Color
* @uiDefault CheckBox.icon.indeterminateBorderColor Color optional; defaults to CheckBox.icon.selectedBorderColor
* @uiDefault CheckBox.icon.indeterminateBackground Color optional; defaults to CheckBox.icon.selectedBackground
* @uiDefault CheckBox.icon.indeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
* *
* @uiDefault CheckBox.icon.disabledBorderColor Color * @uiDefault CheckBox.icon.disabledBorderColor Color
* @uiDefault CheckBox.icon.disabledBackground Color * @uiDefault CheckBox.icon.disabledBackground Color
* @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; CheckBox.icon.disabledBorderColor is used if not specified * @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; defaults to CheckBox.icon.disabledBorderColor
* @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; CheckBox.icon.disabledBackground is used if not specified * @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; defaults to CheckBox.icon.disabledBackground
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color * @uiDefault CheckBox.icon.disabledCheckmarkColor Color
* @uiDefault CheckBox.icon.disabledIndeterminateBorderColor Color optional; defaults to CheckBox.icon.disabledSelectedBorderColor
* @uiDefault CheckBox.icon.disabledIndeterminateBackground Color optional; defaults to CheckBox.icon.disabledSelectedBackground
* @uiDefault CheckBox.icon.disabledIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.disabledCheckmarkColor
* *
* @uiDefault CheckBox.icon.focusedBorderColor Color optional * @uiDefault CheckBox.icon.focusedBorderColor Color optional
* @uiDefault CheckBox.icon.focusedBackground Color optional * @uiDefault CheckBox.icon.focusedBackground Color optional
* @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; CheckBox.icon.focusedBorderColor is used if not specified * @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; defaults to CheckBox.icon.focusedBorderColor
* @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; CheckBox.icon.focusedBackground is used if not specified * @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; defaults to CheckBox.icon.focusedBackground
* @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified * @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
* @uiDefault CheckBox.icon.focusedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.focusedSelectedBorderColor
* @uiDefault CheckBox.icon.focusedIndeterminateBackground Color optional; defaults to CheckBox.icon.focusedSelectedBackground
* @uiDefault CheckBox.icon.focusedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.focusedCheckmarkColor
* *
* @uiDefault CheckBox.icon.hoverBorderColor Color optional * @uiDefault CheckBox.icon.hoverBorderColor Color optional
* @uiDefault CheckBox.icon.hoverBackground Color optional * @uiDefault CheckBox.icon.hoverBackground Color optional
* @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; CheckBox.icon.hoverBorderColor is used if not specified * @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; defaults to CheckBox.icon.hoverBorderColor
* @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; CheckBox.icon.hoverBackground is used if not specified * @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; defaults to CheckBox.icon.hoverBackground
* @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified * @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
* @uiDefault CheckBox.icon.hoverIndeterminateBorderColor Color optional; defaults to CheckBox.icon.hoverSelectedBorderColor
* @uiDefault CheckBox.icon.hoverIndeterminateBackground Color optional; defaults to CheckBox.icon.hoverSelectedBackground
* @uiDefault CheckBox.icon.hoverIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.hoverCheckmarkColor
* *
* @uiDefault CheckBox.icon.pressedBorderColor Color optional * @uiDefault CheckBox.icon.pressedBorderColor Color optional
* @uiDefault CheckBox.icon.pressedBackground Color optional * @uiDefault CheckBox.icon.pressedBackground Color optional
* @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; CheckBox.icon.pressedBorderColor is used if not specified * @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; defaults to CheckBox.icon.pressedBorderColor
* @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; CheckBox.icon.pressedBackground is used if not specified * @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; defaults to CheckBox.icon.pressedBackground
* @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified * @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
* @uiDefault CheckBox.icon.pressedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.pressedSelectedBorderColor
* @uiDefault CheckBox.icon.pressedIndeterminateBackground Color optional; defaults to CheckBox.icon.pressedSelectedBackground
* @uiDefault CheckBox.icon.pressedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.pressedCheckmarkColor
* *
* @author Karl Tauber * @author Karl Tauber
*/ */
@@ -92,6 +110,8 @@ public class FlatCheckBoxIcon
/** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style ); /** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style );
/** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style ); /** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style );
/** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style ); /** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style );
/** @since 3.6 */ @Styleable protected float indeterminateBorderWidth = getUIFloat( "CheckBox.icon.indeterminateBorderWidth", Float.MIN_VALUE, style );
/** @since 3.6 */ @Styleable protected float disabledIndeterminateBorderWidth = getUIFloat( "CheckBox.icon.disabledIndeterminateBorderWidth", Float.MIN_VALUE, style );
@Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 ); @Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
// enabled // enabled
@@ -100,6 +120,9 @@ public class FlatCheckBoxIcon
@Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style ); @Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
@Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style ); @Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
@Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style ); @Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
/** @since 3.6 */ @Styleable protected Color indeterminateBorderColor = getUIColor( "CheckBox.icon.indeterminateBorderColor", style );
/** @since 3.6 */ @Styleable protected Color indeterminateBackground = getUIColor( "CheckBox.icon.indeterminateBackground", style );
/** @since 3.6 */ @Styleable protected Color indeterminateCheckmarkColor = getUIColor( "CheckBox.icon.indeterminateCheckmarkColor", style );
// disabled // disabled
@Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style ); @Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
@@ -107,6 +130,9 @@ public class FlatCheckBoxIcon
/** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style );
/** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style ); /** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style );
@Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style ); @Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateBorderColor = getUIColor( "CheckBox.icon.disabledIndeterminateBorderColor", style );
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateBackground = getUIColor( "CheckBox.icon.disabledIndeterminateBackground", style );
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.disabledIndeterminateCheckmarkColor", style );
// focused // focused
@Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style ); @Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
@@ -114,6 +140,9 @@ public class FlatCheckBoxIcon
/** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style );
/** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style ); /** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style );
/** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style ); /** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style );
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateBorderColor = getUIColor( "CheckBox.icon.focusedIndeterminateBorderColor", style );
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateBackground = getUIColor( "CheckBox.icon.focusedIndeterminateBackground", style );
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.focusedIndeterminateCheckmarkColor", style );
// hover // hover
@Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style ); @Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
@@ -121,6 +150,9 @@ public class FlatCheckBoxIcon
/** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style );
/** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style ); /** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style );
/** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style ); /** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style );
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateBorderColor = getUIColor( "CheckBox.icon.hoverIndeterminateBorderColor", style );
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateBackground = getUIColor( "CheckBox.icon.hoverIndeterminateBackground", style );
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.hoverIndeterminateCheckmarkColor", style );
// pressed // pressed
/** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style ); /** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style );
@@ -128,6 +160,9 @@ public class FlatCheckBoxIcon
/** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style );
/** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style ); /** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style );
/** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style ); /** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style );
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateBorderColor = getUIColor( "CheckBox.icon.pressedIndeterminateBorderColor", style );
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateBackground = getUIColor( "CheckBox.icon.pressedIndeterminateBackground", style );
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.pressedIndeterminateCheckmarkColor", style );
protected String getPropertyPrefix() { protected String getPropertyPrefix() {
return "CheckBox."; return "CheckBox.";
@@ -182,11 +217,17 @@ public class FlatCheckBoxIcon
boolean indeterminate = isIndeterminate( c ); boolean indeterminate = isIndeterminate( c );
boolean selected = indeterminate || isSelected( c ); boolean selected = indeterminate || isSelected( c );
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c ); boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
float bw = selected float bw = Float.MIN_VALUE;
? (disabledSelectedBorderWidth != Float.MIN_VALUE && !c.isEnabled() if( !c.isEnabled() ) {
? disabledSelectedBorderWidth bw = (indeterminate && disabledIndeterminateBorderWidth != Float.MIN_VALUE)
: (selectedBorderWidth != Float.MIN_VALUE ? selectedBorderWidth : borderWidth)) ? disabledIndeterminateBorderWidth
: borderWidth; : (selected ? disabledSelectedBorderWidth : selectedBorderWidth);
}
if( bw == Float.MIN_VALUE ) {
bw = (indeterminate && indeterminateBorderWidth != Float.MIN_VALUE)
? indeterminateBorderWidth
: ((selected && selectedBorderWidth != Float.MIN_VALUE) ? selectedBorderWidth : borderWidth);
}
// paint focused border // paint focused border
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) { if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
@@ -195,15 +236,15 @@ public class FlatCheckBoxIcon
} }
// paint border // paint border
g.setColor( getBorderColor( c, selected ) ); g.setColor( getBorderColor( c, selected, indeterminate ) );
paintBorder( c, g, bw ); paintBorder( c, g, bw );
// paint background // paint background
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ), Color baseBg = stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background );
selected ? selectedBackground : background ); Color bg = FlatUIUtils.deriveColor( getBackground( c, selected, indeterminate ), baseBg );
if( bg.getAlpha() < 255 ) { if( bg.getAlpha() < 255 ) {
// fill background with default color before filling with non-opaque background // fill background with default color before filling with non-opaque background
g.setColor( selected ? selectedBackground : background ); g.setColor( baseBg );
paintBackground( c, g, bw ); paintBackground( c, g, bw );
} }
g.setColor( bg ); g.setColor( bg );
@@ -211,7 +252,7 @@ public class FlatCheckBoxIcon
// paint checkmark // paint checkmark
if( selected ) { if( selected ) {
g.setColor( getCheckmarkColor( c ) ); g.setColor( getCheckmarkColor( c, indeterminate ) );
if( indeterminate ) if( indeterminate )
paintIndeterminate( c, g ); paintIndeterminate( c, g );
else else
@@ -272,30 +313,33 @@ public class FlatCheckBoxIcon
return focusColor; return focusColor;
} }
protected Color getBorderColor( Component c, boolean selected ) { /** @since 3.6 */
protected Color getBorderColor( Component c, boolean selected, boolean indeterminate ) {
return FlatButtonUI.buttonStateColor( c, return FlatButtonUI.buttonStateColor( c,
selected ? selectedBorderColor : borderColor, stateColor( indeterminate, indeterminateBorderColor, selected, selectedBorderColor, borderColor ),
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor, stateColor( indeterminate, disabledIndeterminateBorderColor, selected, disabledSelectedBorderColor, disabledBorderColor ),
(selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor, stateColor( indeterminate, focusedIndeterminateBorderColor, selected, focusedSelectedBorderColor, focusedBorderColor ),
(selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor, stateColor( indeterminate, hoverIndeterminateBorderColor, selected, hoverSelectedBorderColor, hoverBorderColor ),
(selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor ); stateColor( indeterminate, pressedIndeterminateBorderColor, selected, pressedSelectedBorderColor, pressedBorderColor ) );
} }
protected Color getBackground( Component c, boolean selected ) { /** @since 3.6 */
protected Color getBackground( Component c, boolean selected, boolean indeterminate ) {
return FlatButtonUI.buttonStateColor( c, return FlatButtonUI.buttonStateColor( c,
selected ? selectedBackground : background, stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background ),
(selected && disabledSelectedBackground != null) ? disabledSelectedBackground : disabledBackground, stateColor( indeterminate, disabledIndeterminateBackground, selected, disabledSelectedBackground, disabledBackground ),
(selected && focusedSelectedBackground != null) ? focusedSelectedBackground : focusedBackground, stateColor( indeterminate, focusedIndeterminateBackground, selected, focusedSelectedBackground, focusedBackground ),
(selected && hoverSelectedBackground != null) ? hoverSelectedBackground : hoverBackground, stateColor( indeterminate, hoverIndeterminateBackground, selected, hoverSelectedBackground, hoverBackground ),
(selected && pressedSelectedBackground != null) ? pressedSelectedBackground : pressedBackground ); stateColor( indeterminate, pressedIndeterminateBackground, selected, pressedSelectedBackground, pressedBackground ) );
} }
protected Color getCheckmarkColor( Component c ) { /** @since 3.6 */
protected Color getCheckmarkColor( Component c, boolean indeterminate ) {
return FlatButtonUI.buttonStateColor( c, return FlatButtonUI.buttonStateColor( c,
checkmarkColor, stateColor( indeterminate, indeterminateCheckmarkColor, checkmarkColor ),
disabledCheckmarkColor, stateColor( indeterminate, disabledIndeterminateCheckmarkColor, disabledCheckmarkColor ),
focusedCheckmarkColor, stateColor( indeterminate, focusedIndeterminateCheckmarkColor, focusedCheckmarkColor ),
hoverCheckmarkColor, stateColor( indeterminate, hoverIndeterminateCheckmarkColor, hoverCheckmarkColor ),
pressedCheckmarkColor ); stateColor( indeterminate, pressedIndeterminateCheckmarkColor, pressedCheckmarkColor ) );
} }
} }

View File

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

View File

@@ -63,7 +63,7 @@ public class FlatWindowCloseIcon
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
int ix2 = ix + iwh - 1; int ix2 = ix + iwh - 1;
int iy2 = iy + iwh - 1; int iy2 = iy + iwh - 1;
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 ); Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
path.moveTo( ix, iy ); path.moveTo( ix, iy );

View File

@@ -38,7 +38,7 @@ public class FlatWindowIconifyIcon
@Override @Override
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
int iw = (int) (getSymbolHeight() * scaleFactor); int iw = (int) (getSymbolHeight() * scaleFactor);
int ih = (int) scaleFactor; int ih = Math.max( (int) scaleFactor, 1 );
int ix = x + ((width - iw) / 2); int ix = x + ((width - iw) / 2);
int iy = y + ((height - ih) / 2); int iy = y + ((height - ih) / 2);

View File

@@ -42,7 +42,7 @@ public class FlatWindowMaximizeIcon
int iwh = (int) (getSymbolHeight() * scaleFactor); int iwh = (int) (getSymbolHeight() * scaleFactor);
int ix = x + ((width - iwh) / 2); int ix = x + ((width - iwh) / 2);
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
int arc = Math.max( (int) (1.5 * scaleFactor), 2 ); int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
g.fill( SystemInfo.isWindows_11_orLater g.fill( SystemInfo.isWindows_11_orLater

View File

@@ -45,7 +45,7 @@ public class FlatWindowRestoreIcon
int iwh = (int) (getSymbolHeight() * scaleFactor); int iwh = (int) (getSymbolHeight() * scaleFactor);
int ix = x + ((width - iwh) / 2); int ix = x + ((width - iwh) / 2);
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
int arc = Math.max( (int) (1.5 * scaleFactor), 2 ); int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
int arcOuter = (int) (arc + (1.5 * scaleFactor)); int arcOuter = (int) (arc + (1.5 * scaleFactor));

View File

@@ -653,7 +653,8 @@ public class FlatButtonUI
} }
protected Color getBackground( JComponent c ) { protected Color getBackground( JComponent c ) {
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c ); boolean def = isDefaultButton( c );
boolean toolBarButton = !def && (isToolBarButton( c ) || isBorderlessButton( c ));
// selected state // selected state
if( ((AbstractButton)c).isSelected() ) { if( ((AbstractButton)c).isSelected() ) {
@@ -681,7 +682,6 @@ public class FlatButtonUI
toolbarPressedBackground ); toolbarPressedBackground );
} }
boolean def = isDefaultButton( c );
return buttonStateColor( c, return buttonStateColor( c,
getBackgroundBase( c, def ), getBackgroundBase( c, def ),
disabledBackground, disabledBackground,
@@ -733,7 +733,8 @@ public class FlatButtonUI
protected Color getForeground( JComponent c ) { protected Color getForeground( JComponent c ) {
Color fg = c.getForeground(); Color fg = c.getForeground();
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c ); boolean def = isDefaultButton( c );
boolean toolBarButton = !def && (isToolBarButton( c ) || isBorderlessButton( c ));
// selected state // selected state
if( ((AbstractButton)c).isSelected() ) { if( ((AbstractButton)c).isSelected() ) {
@@ -759,7 +760,6 @@ public class FlatButtonUI
toolbarPressedForeground ); toolbarPressedForeground );
} }
boolean def = isDefaultButton( c );
return buttonStateColor( c, return buttonStateColor( c,
getForegroundBase( c, def ), getForegroundBase( c, def ),
disabledText, disabledText,

View File

@@ -585,7 +585,7 @@ public class FlatComboBoxUI
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc ); FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background // paint arrow button background
if( enabled && !isCellRenderer ) { if( enabled && !isCellRenderer && arrowButton.isVisible() ) {
Color buttonColor = paintButton Color buttonColor = paintButton
? buttonEditableBackground ? buttonEditableBackground
: (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox ) : (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox )
@@ -612,7 +612,7 @@ public class FlatComboBoxUI
} }
// paint vertical line between value and arrow button // paint vertical line between value and arrow button
if( paintButton ) { if( paintButton && arrowButton.isVisible() ) {
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor; Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
if( separatorColor != null && buttonSeparatorWidth > 0 ) { if( separatorColor != null && buttonSeparatorWidth > 0 ) {
g2.setColor( separatorColor ); g2.setColor( separatorColor );

View File

@@ -74,7 +74,7 @@ public class FlatDropShadowBorder
this.shadowColor = shadowColor; this.shadowColor = shadowColor;
this.shadowInsets = shadowInsets; this.shadowInsets = shadowInsets;
this.shadowOpacity = shadowOpacity; this.shadowOpacity = Math.min( Math.max( shadowOpacity, 0f ), 1f );
shadowSize = maxInset( shadowInsets ); shadowSize = maxInset( shadowInsets );
} }

View File

@@ -376,31 +376,68 @@ public class FlatFileChooserUI
if( icon != null ) if( icon != null )
return icon; return icon;
// get system icon // new proxy icon
if( f != null ) { //
try { // Note: Since this is a super light weight icon object, we do not add it
icon = getFileChooser().getFileSystemView().getSystemIcon( f ); // to the icon cache here. This keeps cache small in case of large directories
} catch( NullPointerException ex ) { // with thousands of files when icons of all files are only needed to compute
// Java 21 may throw a NPE for exe files that use default Windows exe icon // the layout of list/table, but never painted because located outside of visible area.
} // When an icon needs to be painted, the proxy adds it to the icon cache
// and loads the real icon.
return new FlatFileViewIcon( f );
}
if( icon != null ) { //---- class FlatFileViewIcon -----------------------------------------
if( icon instanceof ImageIcon )
icon = new ScaledImageIcon( (ImageIcon) icon ); /**
cacheIcon( f, icon ); * A proxy icon that has a fixed (scaled) width/height (16x16) and
return icon; * gets/loads the real (system) icon only for painting.
} * Avoids unnecessary getting/loading system icons.
*/
private class FlatFileViewIcon
implements Icon
{
private final File f;
private Icon realIcon;
FlatFileViewIcon( File f ) {
this.f = f;
} }
// get default icon @Override
icon = super.getIcon( f ); public int getIconWidth() {
return UIScale.scale( 16 );
if( icon instanceof ImageIcon ) {
icon = new ScaledImageIcon( (ImageIcon) icon );
cacheIcon( f, icon );
} }
return icon; @Override
public int getIconHeight() {
return UIScale.scale( 16 );
}
@Override
public void paintIcon( Component c, Graphics g, int x, int y ) {
// get icon on demand
if( realIcon == null ) {
// get system icon
try {
if( f != null )
realIcon = getFileChooser().getFileSystemView().getSystemIcon( f );
} catch( NullPointerException ex ) {
// Java 21 may throw a NPE for exe files that use default Windows exe icon
}
// get default icon
if( realIcon == null )
realIcon = FlatFileView.super.getIcon( f );
if( realIcon instanceof ImageIcon )
realIcon = new ScaledImageIcon( (ImageIcon) realIcon );
cacheIcon( f, this );
}
realIcon.paintIcon( c, g, x, y );
}
} }
} }

View File

@@ -17,12 +17,13 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.Color; import java.awt.Color;
import java.awt.Font;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
@@ -74,9 +75,9 @@ public class FlatHTML
for( int i = 1; i <= 7; i++ ) for( int i = 1; i <= 7; i++ )
System.out.println( i+": "+ styleSheet.getPointSize( i ) ); System.out.println( i+": "+ styleSheet.getPointSize( i ) );
debug*/ debug*/
int fontBaseSize = c.getFont().getSize(); Font font = c.getFont();
if( styleSheet.getPointSize( 7 ) != 36f || if( styleSheet.getPointSize( 7 ) != 36f ||
styleSheet.getPointSize( 4 ) == fontBaseSize ) font == null || styleSheet.getPointSize( 4 ) == font.getSize() )
return; return;
// check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size // check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
@@ -93,23 +94,22 @@ debug*/
text = ((JToolTip)c).getTipText(); text = ((JToolTip)c).getTipText();
else else
return; return;
if( text == null ) if( text == null || !BasicHTML.isHTMLString( text ) )
return; return;
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule() // BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>"; String style = "<style>BASE_SIZE " + font.getSize() + "</style>";
String openTag = ""; String openTag = "";
String closeTag = ""; String closeTag = "";
String lowerText = text.toLowerCase( Locale.ENGLISH );
int headIndex; int headIndex;
int styleIndex; int styleIndex;
int insertIndex; int insertIndex;
if( (headIndex = lowerText.indexOf( "<head>" )) >= 0 ) { if( (headIndex = indexOfTag( text, "head", true )) >= 0 ) {
// there is a <head> tag --> insert after <head> tag // there is a <head> tag --> insert after <head> tag
insertIndex = headIndex + "<head>".length(); insertIndex = headIndex;
} else if( (styleIndex = lowerText.indexOf( "<style>" )) >= 0 ) { } else if( (styleIndex = indexOfTag( text, "style", false )) >= 0 ) {
// there is a <style> tag --> insert before <style> tag // there is a <style> tag --> insert before <style> tag
insertIndex = styleIndex; insertIndex = styleIndex;
} else { } else {
@@ -124,6 +124,41 @@ debug*/
+ text.substring( insertIndex ); + text.substring( insertIndex );
BasicHTML.updateRenderer( c, newText ); BasicHTML.updateRenderer( c, newText );
// for unit tests
if( testUpdateRenderer != null )
testUpdateRenderer.accept( c, newText );
}
// for unit tests
static BiConsumer<JComponent, String> testUpdateRenderer;
/**
* Returns start or end index of a HTML tag.
* Checks only for leading '<' character and (case-ignore) tag name.
*/
private static int indexOfTag( String html, String tag, boolean endIndex ) {
int tagLength = tag.length();
int maxLength = html.length() - tagLength - 2;
char lastTagChar = tag.charAt( tagLength - 1 );
for( int i = "<html>".length(); i < maxLength; i++ ) {
// check for leading '<' and last tag name character
if( html.charAt( i ) == '<' && Character.toLowerCase( html.charAt( i + tagLength ) ) == lastTagChar ) {
// compare tag characters from last to first
for( int j = tagLength - 2; j >= 0; j-- ) {
if( Character.toLowerCase( html.charAt( i + 1 + j ) ) != tag.charAt( j ) )
break; // not equal
if( j == 0 ) {
// tag found
return endIndex ? html.indexOf( '>', i + tagLength ) + 1 : i;
}
}
}
}
return -1;
} }
private static final Set<String> absoluteSizeKeywordsSet = new HashSet<>( Arrays.asList( private static final Set<String> absoluteSizeKeywordsSet = new HashSet<>( Arrays.asList(

View File

@@ -57,6 +57,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault List.foreground Color * @uiDefault List.foreground Color
* @uiDefault List.selectionBackground Color * @uiDefault List.selectionBackground Color
* @uiDefault List.selectionForeground Color * @uiDefault List.selectionForeground Color
* @uiDefault List.alternateRowColor Color
* @uiDefault List.dropLineColor Color * @uiDefault List.dropLineColor Color
* @uiDefault List.border Border * @uiDefault List.border Border
* @uiDefault List.cellRenderer ListCellRenderer * @uiDefault List.cellRenderer ListCellRenderer
@@ -93,6 +94,7 @@ public class FlatListUI
@Styleable protected Color selectionForeground; @Styleable protected Color selectionForeground;
@Styleable protected Color selectionInactiveBackground; @Styleable protected Color selectionInactiveBackground;
@Styleable protected Color selectionInactiveForeground; @Styleable protected Color selectionInactiveForeground;
/** @since 3.6 */ @Styleable protected Color alternateRowColor;
/** @since 3 */ @Styleable protected Insets selectionInsets; /** @since 3 */ @Styleable protected Insets selectionInsets;
/** @since 3 */ @Styleable protected int selectionArc; /** @since 3 */ @Styleable protected int selectionArc;
@@ -129,6 +131,7 @@ public class FlatListUI
selectionForeground = UIManager.getColor( "List.selectionForeground" ); selectionForeground = UIManager.getColor( "List.selectionForeground" );
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" ); selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" ); selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
alternateRowColor = UIManager.getColor( "List.alternateRowColor" );
selectionInsets = UIManager.getInsets( "List.selectionInsets" ); selectionInsets = UIManager.getInsets( "List.selectionInsets" );
selectionArc = UIManager.getInt( "List.selectionArc" ); selectionArc = UIManager.getInt( "List.selectionArc" );
@@ -143,6 +146,7 @@ public class FlatListUI
selectionForeground = null; selectionForeground = null;
selectionInactiveBackground = null; selectionInactiveBackground = null;
selectionInactiveForeground = null; selectionInactiveForeground = null;
alternateRowColor = null;
oldStyleValues = null; oldStyleValues = null;
} }
@@ -299,13 +303,24 @@ public class FlatListUI
{ {
boolean isSelected = selModel.isSelectedIndex( row ); boolean isSelected = selModel.isSelectedIndex( row );
// paint alternating rows
if( alternateRowColor != null && row % 2 != 0 &&
!"ComboBox.list".equals( list.getName() ) ) // combobox does not support alternate row color
{
g.setColor( alternateRowColor );
float arc = UIScale.scale( selectionArc / 2f );
FlatUIUtils.paintSelection( (Graphics2D) g, rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height,
UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
}
// get renderer component // get renderer component
@SuppressWarnings( "unchecked" ) @SuppressWarnings( "unchecked" )
Component rendererComponent = cellRenderer.getListCellRendererComponent( list, Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
dataModel.getElementAt( row ), row, isSelected, dataModel.getElementAt( row ), row, isSelected,
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) ); FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );
// // use smaller cell width if list is used in JFileChooser
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) ); boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
int cx, cw; int cx, cw;
if( isFileList ) { if( isFileList ) {

View File

@@ -90,10 +90,10 @@ class FlatNativeLibrary
classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64"; classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64";
ext = "dylib"; ext = "dylib";
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) { } else if( SystemInfo.isLinux && (SystemInfo.isX86_64 || SystemInfo.isAARCH64)) {
// Linux: requires x86_64 // Linux: requires x86_64 or aarch64
classifier = "linux-x86_64"; classifier = SystemInfo.isAARCH64 ? "linux-arm64" : "linux-x86_64";
ext = "so"; ext = "so";
// Load libjawt.so (part of JRE) explicitly because it is not found // Load libjawt.so (part of JRE) explicitly because it is not found

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.GraphicsConfiguration;
import java.awt.Point; import java.awt.Point;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
@@ -96,7 +97,11 @@ class FlatNativeLinuxLibrary
} }
private static Point scale( Window window, Point pt ) { private static Point scale( Window window, Point pt ) {
AffineTransform transform = window.getGraphicsConfiguration().getDefaultTransform(); GraphicsConfiguration gc = window.getGraphicsConfiguration();
if( gc == null )
return pt;
AffineTransform transform = gc.getDefaultTransform();
int x = (int) Math.round( pt.x * transform.getScaleX() ); int x = (int) Math.round( pt.x * transform.getScaleX() );
int y = (int) Math.round( pt.y * transform.getScaleY() ); int y = (int) Math.round( pt.y * transform.getScaleY() );
return new Point( x, y ); return new Point( x, y );

View File

@@ -25,6 +25,7 @@ import java.awt.Dimension;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsDevice.WindowTranslucency;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.Insets; import java.awt.Insets;
import java.awt.MouseInfo; import java.awt.MouseInfo;
@@ -36,6 +37,8 @@ import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.WindowFocusListener; import java.awt.event.WindowFocusListener;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@@ -43,6 +46,7 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLayeredPane; import javax.swing.JLayeredPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@@ -60,6 +64,7 @@ import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.BasicComboPopup;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -113,14 +118,8 @@ public class FlatPopupFactory
// macOS and Linux adds drop shadow to heavy weight popups // macOS and Linux adds drop shadow to heavy weight popups
if( SystemInfo.isMacOS || SystemInfo.isLinux ) { if( SystemInfo.isMacOS || SystemInfo.isLinux ) {
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents ); NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
if( popup.popupWindow != null && SystemInfo.isMacOS && if( popup.popupWindow != null && (isMacOSBorderSupported() || isLinuxBorderSupported( popup.popupWindow )) )
// do not use rounded border on macOS 14.4+ because it may freeze the application setupRoundedBorder( popup, popup.popupWindow, owner, contents );
// and crash the macOS WindowServer process (reports vary from Finder restarts to OS restarts)
// https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215
// https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442
SystemInfo.osVersion < SystemInfo.toVersion( 14, 4, 0, 0 ) &&
FlatNativeMacLibrary.isLoaded() )
setupRoundedBorder( popup.popupWindow, owner, contents );
return popup; return popup;
} }
@@ -130,7 +129,7 @@ public class FlatPopupFactory
{ {
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents ); NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
if( popup.popupWindow != null ) if( popup.popupWindow != null )
setupRoundedBorder( popup.popupWindow, owner, contents ); setupRoundedBorder( popup, popup.popupWindow, owner, contents );
return popup; return popup;
} }
@@ -140,7 +139,8 @@ public class FlatPopupFactory
// create drop shadow popup // create drop shadow popup
Popup popupForScreenOfOwner = getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ); Popup popupForScreenOfOwner = getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight );
return owner.getGraphicsConfiguration().isTranslucencyCapable() GraphicsConfiguration gc = (owner != null) ? owner.getGraphicsConfiguration() : null;
return (gc != null && gc.isTranslucencyCapable())
? new DropShadowPopup( popupForScreenOfOwner, owner, contents ) ? new DropShadowPopup( popupForScreenOfOwner, owner, contents )
: new NonFlashingPopup( popupForScreenOfOwner, owner, contents ); : new NonFlashingPopup( popupForScreenOfOwner, owner, contents );
} }
@@ -307,7 +307,7 @@ public class FlatPopupFactory
break; break;
} }
} }
if( gc == null ) if( gc == null && owner != null )
gc = owner.getGraphicsConfiguration(); gc = owner.getGraphicsConfiguration();
if( gc == null ) if( gc == null )
return null; return null;
@@ -360,19 +360,31 @@ public class FlatPopupFactory
//---- native rounded border ---------------------------------------------- //---- native rounded border ----------------------------------------------
private static boolean isWindows11BorderSupported() { private static boolean isWindows11BorderSupported() {
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded(); return SystemInfo.isWindows_11_orLater &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
FlatNativeWindowsLibrary.isLoaded();
} }
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) { private static boolean isMacOSBorderSupported() {
// make sure that the native window is created return SystemInfo.isMacOS &&
if( !popupWindow.isDisplayable() ) FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
popupWindow.addNotify(); FlatNativeMacLibrary.isLoaded();
}
private static boolean isLinuxBorderSupported( Window window ) {
return SystemInfo.isLinux &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
window.getGraphicsConfiguration().getDevice().isWindowTranslucencySupported( WindowTranslucency.PERPIXEL_TRANSPARENT );
}
private static void setupRoundedBorder( NonFlashingPopup popup,
Window popupWindow, Component owner, Component contents )
{
int borderCornerRadius = getBorderCornerRadius( owner, contents ); int borderCornerRadius = getBorderCornerRadius( owner, contents );
float borderWidth = getRoundedBorderWidth( owner, contents ); float borderWidth = getRoundedBorderWidth( owner, contents );
// get Swing border color // get Swing border color
Color borderColor = null; // use system default color Color borderColor;
if( contents instanceof JComponent ) { if( contents instanceof JComponent ) {
Border border = ((JComponent)contents).getBorder(); Border border = ((JComponent)contents).getBorder();
border = FlatUIUtils.unwrapNonUIResourceBorder( border ); border = FlatUIUtils.unwrapNonUIResourceBorder( border );
@@ -384,11 +396,35 @@ public class FlatPopupFactory
borderColor = ((LineBorder)border).getLineColor(); borderColor = ((LineBorder)border).getLineColor();
else if( border instanceof EmptyBorder ) else if( border instanceof EmptyBorder )
borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
else
borderColor = null; // use system default color
// avoid that FlatLineBorder paints the Swing border // avoid that FlatLineBorder paints the Swing border
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true ); ((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true );
} } else
borderColor = null; // use system default color
if( popupWindow.isDisplayable() ) {
// native window already created
setupRoundedBorderImpl( popup, popupWindow, borderCornerRadius, borderWidth, borderColor );
} else {
// native window not yet created --> add listener to set native border after window creation
AtomicReference<HierarchyListener> l = new AtomicReference<>();
l.set( e -> {
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
(e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 )
{
setupRoundedBorderImpl( popup, popupWindow, borderCornerRadius, borderWidth, borderColor );
popupWindow.removeHierarchyListener( l.get() );
}
} );
popupWindow.addHierarchyListener( l.get() );
}
}
private static void setupRoundedBorderImpl( NonFlashingPopup popup,
Window popupWindow, int borderCornerRadius, float borderWidth, Color borderColor )
{
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
// get native window handle // get native window handle
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow ); long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
@@ -408,6 +444,12 @@ public class FlatPopupFactory
// set corner radius, border width and color // set corner radius, border width and color
FlatNativeMacLibrary.setWindowRoundedBorder( popupWindow, borderCornerRadius, FlatNativeMacLibrary.setWindowRoundedBorder( popupWindow, borderCornerRadius,
borderWidth, (borderColor != null) ? borderColor.getRGB() : 0 ); borderWidth, (borderColor != null) ? borderColor.getRGB() : 0 );
} else if( SystemInfo.isLinux ) {
if( popupWindow instanceof RootPaneContainer ) {
popup.windowRoundedBorder = new FlatWindowRoundedBorder(
((RootPaneContainer)popupWindow).getRootPane(),
borderCornerRadius, borderWidth, borderColor );
}
} }
} }
@@ -440,7 +482,7 @@ public class FlatPopupFactory
"Popup.roundedBorderWidth"; "Popup.roundedBorderWidth";
Object value = getOption( owner, contents, FlatClientProperties.POPUP_ROUNDED_BORDER_WIDTH, uiKey ); Object value = getOption( owner, contents, FlatClientProperties.POPUP_ROUNDED_BORDER_WIDTH, uiKey );
return (value instanceof Number) ? ((Number)value).floatValue() : 0; return (value instanceof Number) ? ((Number)value).floatValue() : 1;
} }
//---- fixes -------------------------------------------------------------- //---- fixes --------------------------------------------------------------
@@ -553,6 +595,7 @@ public class FlatPopupFactory
// heavy weight // heavy weight
Window popupWindow; Window popupWindow;
private Color oldPopupWindowBackground; private Color oldPopupWindowBackground;
private FlatWindowRoundedBorder windowRoundedBorder;
private boolean disposed; private boolean disposed;
@@ -578,6 +621,7 @@ public class FlatPopupFactory
contents = reusePopup.contents; contents = reusePopup.contents;
popupWindow = reusePopup.popupWindow; popupWindow = reusePopup.popupWindow;
oldPopupWindowBackground = reusePopup.oldPopupWindowBackground; oldPopupWindowBackground = reusePopup.oldPopupWindowBackground;
windowRoundedBorder = reusePopup.windowRoundedBorder;
} }
NonFlashingPopup cloneForReuse() { NonFlashingPopup cloneForReuse() {
@@ -649,6 +693,11 @@ public class FlatPopupFactory
contents = null; contents = null;
} }
if( windowRoundedBorder != null ) {
windowRoundedBorder.uninstall();
windowRoundedBorder = null;
}
if( popupWindow != null ) { if( popupWindow != null ) {
// restore background so that it can not affect other LaFs (when switching) // restore background so that it can not affect other LaFs (when switching)
// because popup windows are cached and reused // because popup windows are cached and reused
@@ -665,8 +714,6 @@ public class FlatPopupFactory
Container contentPane = ((JWindow)popupWindow).getContentPane(); Container contentPane = ((JWindow)popupWindow).getContentPane();
contentPane.removeAll(); contentPane.removeAll();
contentPane.add( contents, BorderLayout.CENTER ); contentPane.add( contents, BorderLayout.CENTER );
popupWindow.invalidate();
popupWindow.validate();
popupWindow.pack(); popupWindow.pack();
// update client property on contents // update client property on contents
@@ -686,6 +733,7 @@ public class FlatPopupFactory
private class DropShadowPopup private class DropShadowPopup
extends NonFlashingPopup extends NonFlashingPopup
implements ComponentListener
{ {
// light weight // light weight
private JComponent lightComp; private JComponent lightComp;
@@ -745,7 +793,7 @@ public class FlatPopupFactory
} }
// Windows 11: reset corner preference on reused heavy weight popups // Windows 11: reset corner preference on reused heavy weight popups
if( isWindows11BorderSupported() ) { if( SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded() ) {
resetWindows11Border( popupWindow ); resetWindows11Border( popupWindow );
if( dropShadowWindow != null ) if( dropShadowWindow != null )
resetWindows11Border( dropShadowWindow ); resetWindows11Border( dropShadowWindow );
@@ -815,10 +863,18 @@ public class FlatPopupFactory
if( insets.left != 0 || insets.top != 0 ) if( insets.left != 0 || insets.top != 0 )
lightComp.setLocation( lightComp.getX() - insets.left, lightComp.getY() - insets.top ); lightComp.setLocation( lightComp.getX() - insets.left, lightComp.getY() - insets.top );
} }
if( popupWindow != null ) {
removeAllPopupWindowComponentListeners();
popupWindow.addComponentListener( this );
}
} }
@Override @Override
void hideImpl() { void hideImpl() {
if( popupWindow != null )
removeAllPopupWindowComponentListeners();
if( dropShadowDelegate != null ) { if( dropShadowDelegate != null ) {
dropShadowDelegate.hide(); dropShadowDelegate.hide();
dropShadowDelegate = null; dropShadowDelegate = null;
@@ -918,22 +974,55 @@ public class FlatPopupFactory
@Override @Override
void reset( Component contents, int ownerX, int ownerY ) { void reset( Component contents, int ownerX, int ownerY ) {
if( popupWindow != null )
removeAllPopupWindowComponentListeners();
super.reset( contents, ownerX, ownerY ); super.reset( contents, ownerX, ownerY );
if( dropShadowWindow != null ) { updateDropShadowWindowBounds();
// set preferred size of drop shadow panel }
Dimension prefSize = popupWindow.getPreferredSize();
Insets insets = dropShadowPanel2.getInsets();
int w = prefSize.width + insets.left + insets.right;
int h = prefSize.height + insets.top + insets.bottom;
dropShadowPanel2.setPreferredSize( new Dimension( w, h ) );
// update drop shadow popup window location and size private void updateDropShadowWindowBounds() {
int x = popupWindow.getX() - insets.left; if( dropShadowWindow == null )
int y = popupWindow.getY() - insets.top; return;
dropShadowWindow.setBounds( x, y, w, h );
dropShadowWindow.pack(); // calculate size of drop shadow window
Dimension size = popupWindow.getSize();
Insets insets = dropShadowPanel2.getInsets();
int w = size.width + insets.left + insets.right;
int h = size.height + insets.top + insets.bottom;
// update drop shadow popup window bounds
int x = popupWindow.getX() - insets.left;
int y = popupWindow.getY() - insets.top;
dropShadowWindow.setBounds( x, y, w, h );
dropShadowWindow.validate();
}
private void removeAllPopupWindowComponentListeners() {
// make sure that there is no old component listener
// necessary because this class is cloned if reusing popup windows
for( ComponentListener l : popupWindow.getComponentListeners() ) {
if( l instanceof DropShadowPopup )
popupWindow.removeComponentListener( l );
} }
} }
//---- interface ComponentListener ----
@Override
public void componentResized( ComponentEvent e ) {
if( e.getSource() == popupWindow )
updateDropShadowWindowBounds();
}
@Override
public void componentMoved( ComponentEvent e ) {
if( e.getSource() == popupWindow )
updateDropShadowWindowBounds();
}
@Override public void componentShown( ComponentEvent e ) {}
@Override public void componentHidden( ComponentEvent e ) {}
} }
} }

View File

@@ -239,11 +239,13 @@ public class FlatPopupMenuUI
if( gc == null && popupMenu.getInvoker() != null ) if( gc == null && popupMenu.getInvoker() != null )
gc = popupMenu.getInvoker().getGraphicsConfiguration(); gc = popupMenu.getInvoker().getGraphicsConfiguration();
// compute screen height if( gc == null )
return new Rectangle( Toolkit.getDefaultToolkit().getScreenSize() );
// compute screen bounds
// (always subtract screen insets because there is no API to detect whether // (always subtract screen insets because there is no API to detect whether
// the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar()) // the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar())
Toolkit toolkit = Toolkit.getDefaultToolkit(); Rectangle screenBounds = gc.getBounds();
Rectangle screenBounds = (gc != null) ? gc.getBounds() : new Rectangle( toolkit.getScreenSize() );
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc ); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
return FlatUIUtils.subtractInsets( screenBounds, screenInsets ); return FlatUIUtils.subtractInsets( screenBounds, screenInsets );
} }

View File

@@ -448,6 +448,11 @@ public class FlatRootPaneUI
titlePane.titleBarColorsChanged(); titlePane.titleBarColorsChanged();
break; break;
case FlatClientProperties.TITLE_BAR_HEIGHT:
if( titlePane != null )
titlePane.revalidate();
break;
case FlatClientProperties.FULL_WINDOW_CONTENT: case FlatClientProperties.FULL_WINDOW_CONTENT:
if( titlePane != null ) { if( titlePane != null ) {
rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() ); rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() );
@@ -679,7 +684,7 @@ public class FlatRootPaneUI
* Window border used for non-native window decorations. * Window border used for non-native window decorations.
*/ */
public static class FlatWindowBorder public static class FlatWindowBorder
extends BorderUIResource.EmptyBorderUIResource extends FlatEmptyBorder
{ {
protected final Color activeBorderColor = UIManager.getColor( "RootPane.activeBorderColor" ); protected final Color activeBorderColor = UIManager.getColor( "RootPane.activeBorderColor" );
protected final Color inactiveBorderColor = UIManager.getColor( "RootPane.inactiveBorderColor" ); protected final Color inactiveBorderColor = UIManager.getColor( "RootPane.inactiveBorderColor" );
@@ -712,7 +717,10 @@ public class FlatRootPaneUI
} }
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
g.drawRect( x, y, width - 1, height - 1 ); Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
float lineWidth = (float) (UIScale.scale( 1f ) * scaleFactor);
g.fill( FlatUIUtils.createRectangle( x, y, width, height, lineWidth ) );
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
} }
protected boolean isWindowMaximized( Component c ) { protected boolean isWindowMaximized( Component c ) {

View File

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

View File

@@ -2306,8 +2306,23 @@ debug*/
/** @since 3.4 */ /** @since 3.4 */
@Override @Override
public Boolean isTitleBarCaptionAt( int x, int y ) { public Boolean isTitleBarCaptionAt( int x, int y ) {
if( tabForCoordinate( tabPane, x, y ) >= 0 ) // Note: not using tabForCoordinate() here because this may validate layout and cause dead lock
return false;
if( moreTabsButton != null ) {
// convert x,y from JTabbedPane coordinate space to ScrollableTabPanel coordinate space
Point viewPosition = tabViewport.getViewPosition();
x = x - tabViewport.getX() + viewPosition.x;
y = y - tabViewport.getY() + viewPosition.y;
// check whether point is within viewport
if( !tabViewport.getViewRect().contains( x, y ) )
return null; // check children
}
for( int i = 0; i < rects.length; i++ ) {
if( rects[i].contains( x, y ) )
return false;
}
return null; // check children return null; // check children
} }

View File

@@ -359,6 +359,10 @@ public class FlatTitlePane
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize(); Dimension size = super.getPreferredSize();
int titleBarHeight = clientPropertyInt( rootPane, TITLE_BAR_HEIGHT, -1 );
if( titleBarHeight >= 0 )
return new Dimension( size.width, UIScale.scale( titleBarHeight ) );
if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) { if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) {
// make title pane height smaller when frame is maximized // make title pane height smaller when frame is maximized
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) ); size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) );
@@ -395,6 +399,12 @@ public class FlatTitlePane
// allow the button to shrink if space is rare // allow the button to shrink if space is rare
return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height ); return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height );
} }
@Override
public Dimension getMaximumSize() {
// allow the button to fill whole button area height
// see also BasicMenuUI.getMaximumSize()
return new Dimension( super.getMaximumSize().width, Short.MAX_VALUE );
}
}; };
button.setFocusable( false ); button.setFocusable( false );
button.setContentAreaFilled( false ); button.setContentAreaFilled( false );
@@ -814,7 +824,8 @@ public class FlatTitlePane
Rectangle oldMaximizedBounds = frame.getMaximizedBounds(); Rectangle oldMaximizedBounds = frame.getMaximizedBounds();
if( !hasNativeCustomDecoration() && if( !hasNativeCustomDecoration() &&
(oldMaximizedBounds == null || (oldMaximizedBounds == null ||
Objects.equals( oldMaximizedBounds, rootPane.getClientProperty( "_flatlaf.maximizedBounds" ) )) ) Objects.equals( oldMaximizedBounds, rootPane.getClientProperty( "_flatlaf.maximizedBounds" ) )) &&
window.getGraphicsConfiguration() != null )
{ {
GraphicsConfiguration gc = window.getGraphicsConfiguration(); GraphicsConfiguration gc = window.getGraphicsConfiguration();
@@ -1048,10 +1059,11 @@ public class FlatTitlePane
* <p> * <p>
* Note: * Note:
* <ul> * <ul>
* <li>This method is invoked often when mouse is moved over title bar * <li>This method is invoked often when mouse is moved over window title bar area
* and should therefore return quickly. * and should therefore return quickly.
* <li>This method is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread) * <li>This method is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
* while processing Windows messages. * while processing Windows messages.
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
* </ul> * </ul>
*/ */
private boolean captionHitTest( Point pt ) { private boolean captionHitTest( Point pt ) {
@@ -1079,7 +1091,7 @@ public class FlatTitlePane
} }
private boolean isTitleBarCaptionAt( Component c, int x, int y ) { private boolean isTitleBarCaptionAt( Component c, int x, int y ) {
if( !c.isDisplayable() || !c.isVisible() || !c.contains( x, y ) || c == mouseLayer ) if( !c.isDisplayable() || !c.isVisible() || !contains( c, x, y ) || c == mouseLayer )
return true; // continue checking with next component return true; // continue checking with next component
if( c.isEnabled() && if( c.isEnabled() &&
@@ -1097,8 +1109,18 @@ public class FlatTitlePane
// if component is not fully layouted, do not invoke function // if component is not fully layouted, do not invoke function
// because it is too dangerous that the function tries to layout the component, // because it is too dangerous that the function tries to layout the component,
// which could cause a dead lock // which could cause a dead lock
if( !c.isValid() ) if( !c.isValid() ) {
// revalidate if necessary so that it is valid when invoked again later
EventQueue.invokeLater( () -> {
Window w = SwingUtilities.windowForComponent( c );
if( w != null )
w.revalidate();
else
c.revalidate();
} );
return false; // assume that this is not a caption because the component has mouse listeners return false; // assume that this is not a caption because the component has mouse listeners
}
if( caption instanceof Function ) { if( caption instanceof Function ) {
// check client property function value // check client property function value
@@ -1131,6 +1153,16 @@ public class FlatTitlePane
return true; return true;
} }
/**
* Same as {@link Component#contains(int, int)}, but not using that method
* because it may be overridden by custom components and invoke code that
* tries to request AWT tree lock on 'AWT-Windows' thread.
* This could freeze the application if AWT tree is already locked on 'AWT-EventQueue' thread.
*/
private boolean contains( Component c, int x, int y ) {
return x >= 0 && y >= 0 && x < c.getWidth() && y < c.getHeight();
}
private int lastCaptionHitTestX; private int lastCaptionHitTestX;
private int lastCaptionHitTestY; private int lastCaptionHitTestY;
private long lastCaptionHitTestTime; private long lastCaptionHitTestTime;
@@ -1558,6 +1590,15 @@ debug*/
* Useful for components that do not use mouse input on whole component bounds. * 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 * E.g. a tabbed pane with a few tabs has some empty space beside the tabs
* that can be used to move the window. * that can be used to move the window.
* <p>
* Note:
* <ul>
* <li>This method is invoked often when mouse is moved over window title bar area
* and should therefore return quickly.
* <li>This method 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>
* *
* @return {@code true} if the component is not interested in mouse input at the given location * @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 false} if the component wants process mouse input at the given location

View File

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

View File

@@ -102,9 +102,11 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault Tree.selectionForeground Color * @uiDefault Tree.selectionForeground Color
* @uiDefault Tree.selectionInactiveBackground Color * @uiDefault Tree.selectionInactiveBackground Color
* @uiDefault Tree.selectionInactiveForeground Color * @uiDefault Tree.selectionInactiveForeground Color
* @uiDefault Tree.alternateRowColor Color
* @uiDefault Tree.selectionInsets Insets * @uiDefault Tree.selectionInsets Insets
* @uiDefault Tree.selectionArc int * @uiDefault Tree.selectionArc int
* @uiDefault Tree.wideSelection boolean * @uiDefault Tree.wideSelection boolean
* @uiDefault Tree.wideCellRenderer boolean
* @uiDefault Tree.showCellFocusIndicator boolean * @uiDefault Tree.showCellFocusIndicator boolean
* @uiDefault Tree.showDefaultIcons boolean * @uiDefault Tree.showDefaultIcons boolean
* *
@@ -141,9 +143,11 @@ public class FlatTreeUI
@Styleable protected Color selectionInactiveBackground; @Styleable protected Color selectionInactiveBackground;
@Styleable protected Color selectionInactiveForeground; @Styleable protected Color selectionInactiveForeground;
@Styleable protected Color selectionBorderColor; @Styleable protected Color selectionBorderColor;
/** @since 3.6 */ @Styleable protected Color alternateRowColor;
/** @since 3 */ @Styleable protected Insets selectionInsets; /** @since 3 */ @Styleable protected Insets selectionInsets;
/** @since 3 */ @Styleable protected int selectionArc; /** @since 3 */ @Styleable protected int selectionArc;
@Styleable protected boolean wideSelection; @Styleable protected boolean wideSelection;
/** @since 3.6 */ @Styleable protected boolean wideCellRenderer;
@Styleable protected boolean showCellFocusIndicator; @Styleable protected boolean showCellFocusIndicator;
/** @since 3 */ protected boolean showDefaultIcons; /** @since 3 */ protected boolean showDefaultIcons;
@@ -192,9 +196,11 @@ public class FlatTreeUI
selectionInactiveBackground = UIManager.getColor( "Tree.selectionInactiveBackground" ); selectionInactiveBackground = UIManager.getColor( "Tree.selectionInactiveBackground" );
selectionInactiveForeground = UIManager.getColor( "Tree.selectionInactiveForeground" ); selectionInactiveForeground = UIManager.getColor( "Tree.selectionInactiveForeground" );
selectionBorderColor = UIManager.getColor( "Tree.selectionBorderColor" ); selectionBorderColor = UIManager.getColor( "Tree.selectionBorderColor" );
alternateRowColor = UIManager.getColor( "Tree.alternateRowColor" );
selectionInsets = UIManager.getInsets( "Tree.selectionInsets" ); selectionInsets = UIManager.getInsets( "Tree.selectionInsets" );
selectionArc = UIManager.getInt( "Tree.selectionArc" ); selectionArc = UIManager.getInt( "Tree.selectionArc" );
wideSelection = UIManager.getBoolean( "Tree.wideSelection" ); wideSelection = UIManager.getBoolean( "Tree.wideSelection" );
wideCellRenderer = UIManager.getBoolean( "Tree.wideCellRenderer" );
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" ); showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
showDefaultIcons = UIManager.getBoolean( "Tree.showDefaultIcons" ); showDefaultIcons = UIManager.getBoolean( "Tree.showDefaultIcons" );
@@ -227,6 +233,7 @@ public class FlatTreeUI
selectionInactiveBackground = null; selectionInactiveBackground = null;
selectionInactiveForeground = null; selectionInactiveForeground = null;
selectionBorderColor = null; selectionBorderColor = null;
alternateRowColor = null;
defaultLeafIcon = null; defaultLeafIcon = null;
defaultClosedIcon = null; defaultClosedIcon = null;
@@ -310,6 +317,7 @@ public class FlatTreeUI
if( e.getSource() == tree ) { if( e.getSource() == tree ) {
switch( e.getPropertyName() ) { switch( e.getPropertyName() ) {
case TREE_WIDE_SELECTION: case TREE_WIDE_SELECTION:
case TREE_WIDE_CELL_RENDERER:
case TREE_PAINT_SELECTION: case TREE_PAINT_SELECTION:
HiDPIUtils.repaint( tree ); HiDPIUtils.repaint( tree );
break; break;
@@ -571,6 +579,27 @@ public class FlatTreeUI
boolean isDropRow = isDropRow( row ); boolean isDropRow = isDropRow( row );
boolean needsSelectionPainting = (isSelected || isDropRow) && isPaintSelection(); boolean needsSelectionPainting = (isSelected || isDropRow) && isPaintSelection();
// paint alternating rows
if( alternateRowColor != null && row % 2 != 0 ) {
g.setColor( alternateRowColor );
float arc = UIScale.scale( selectionArc / 2f );
FlatUIUtils.paintSelection( (Graphics2D) g, 0, bounds.y, tree.getWidth(), bounds.height,
UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
}
// update bounds for wide cell renderer
if( isWideSelection() && isWideCellRenderer() ) {
Rectangle wideBounds = new Rectangle( bounds );
if( tree.getComponentOrientation().isLeftToRight() )
wideBounds.width = tree.getWidth() - bounds.x - insets.right;
else {
wideBounds.x = insets.left;
wideBounds.width = bounds.x + bounds.width - insets.left;
}
bounds = wideBounds;
}
// do not paint row if editing // do not paint row if editing
if( isEditing ) { if( isEditing ) {
// paint wide selection // paint wide selection
@@ -795,6 +824,11 @@ public class FlatTreeUI
return clientPropertyBoolean( tree, TREE_WIDE_SELECTION, wideSelection ); return clientPropertyBoolean( tree, TREE_WIDE_SELECTION, wideSelection );
} }
/** @since 3.6 */
protected boolean isWideCellRenderer() {
return clientPropertyBoolean( tree, TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}
protected boolean isPaintSelection() { protected boolean isPaintSelection() {
return clientPropertyBoolean( tree, TREE_PAINT_SELECTION, paintSelection ); return clientPropertyBoolean( tree, TREE_PAINT_SELECTION, paintSelection );
} }

View File

@@ -129,6 +129,20 @@ public class FlatUIUtils
return insets.top == 0 && insets.left == 0 && insets.bottom == 0 && insets.right == 0; return insets.top == 0 && insets.left == 0 && insets.bottom == 0 && insets.right == 0;
} }
/** @since 3.6 */
public static Color stateColor( boolean state, Color stateColor, Color defaultColor ) {
return (state && stateColor != null) ? stateColor : defaultColor;
}
/** @since 3.6 */
public static Color stateColor( boolean state1, Color state1Color,
boolean state2, Color state2Color, Color defaultColor )
{
return (state1 && state1Color != null)
? state1Color
: ((state2 && state2Color != null) ? state2Color : defaultColor);
}
public static Color getUIColor( String key, int defaultColorRGB ) { public static Color getUIColor( String key, int defaultColorRGB ) {
Color color = UIManager.getColor( key ); Color color = UIManager.getColor( key );
return (color != null) ? color : new Color( defaultColorRGB ); return (color != null) ? color : new Color( defaultColorRGB );
@@ -397,7 +411,8 @@ public class FlatUIUtils
GraphicsConfiguration gc = c.getGraphicsConfiguration(); GraphicsConfiguration gc = c.getGraphicsConfiguration();
GraphicsDevice gd = (gc != null) ? gc.getDevice() : null; GraphicsDevice gd = (gc != null) ? gc.getDevice() : null;
Window fullScreenWindow = (gd != null) ? gd.getFullScreenWindow() : null; Window fullScreenWindow = (gd != null) ? gd.getFullScreenWindow() : null;
return (fullScreenWindow != null && fullScreenWindow == SwingUtilities.windowForComponent( c )); return (fullScreenWindow != null &&
(fullScreenWindow == c || fullScreenWindow == SwingUtilities.windowForComponent( c )));
} }
public static Boolean isRoundRect( Component c ) { public static Boolean isRoundRect( Component c ) {

View File

@@ -41,7 +41,7 @@ import java.util.function.Supplier;
import javax.swing.DesktopManager; import javax.swing.DesktopManager;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JInternalFrame; import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane; import javax.swing.JPanel;
import javax.swing.JRootPane; import javax.swing.JRootPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
@@ -59,8 +59,6 @@ import com.formdev.flatlaf.util.UIScale;
public abstract class FlatWindowResizer public abstract class FlatWindowResizer
implements PropertyChangeListener, ComponentListener implements PropertyChangeListener, ComponentListener
{ {
protected final static Integer WINDOW_RESIZER_LAYER = JLayeredPane.DRAG_LAYER + 1;
protected final JComponent resizeComp; protected final JComponent resizeComp;
protected final int borderDragThickness = FlatUIUtils.getUIInt( "RootPane.borderDragThickness", 5 ); protected final int borderDragThickness = FlatUIUtils.getUIInt( "RootPane.borderDragThickness", 5 );
@@ -81,12 +79,12 @@ public abstract class FlatWindowResizer
leftDragComp = createDragBorderComponent( NW_RESIZE_CURSOR, W_RESIZE_CURSOR, SW_RESIZE_CURSOR ); leftDragComp = createDragBorderComponent( NW_RESIZE_CURSOR, W_RESIZE_CURSOR, SW_RESIZE_CURSOR );
rightDragComp = createDragBorderComponent( NE_RESIZE_CURSOR, E_RESIZE_CURSOR, SE_RESIZE_CURSOR ); rightDragComp = createDragBorderComponent( NE_RESIZE_CURSOR, E_RESIZE_CURSOR, SE_RESIZE_CURSOR );
Container cont = (resizeComp instanceof JRootPane) ? ((JRootPane)resizeComp).getLayeredPane() : resizeComp; // for rootpanes, add after glasspane
Object cons = (cont instanceof JLayeredPane) ? WINDOW_RESIZER_LAYER : null; int insertIndex = (resizeComp instanceof JRootPane) ? 1 : 0;
cont.add( topDragComp, cons, 0 ); resizeComp.add( topDragComp, insertIndex++ );
cont.add( bottomDragComp, cons, 1 ); resizeComp.add( bottomDragComp, insertIndex++ );
cont.add( leftDragComp, cons, 2 ); resizeComp.add( leftDragComp, insertIndex++ );
cont.add( rightDragComp, cons, 3 ); resizeComp.add( rightDragComp, insertIndex++ );
resizeComp.addComponentListener( this ); resizeComp.addComponentListener( this );
resizeComp.addPropertyChangeListener( "ancestor", this ); resizeComp.addPropertyChangeListener( "ancestor", this );
@@ -105,11 +103,10 @@ public abstract class FlatWindowResizer
resizeComp.removeComponentListener( this ); resizeComp.removeComponentListener( this );
resizeComp.removePropertyChangeListener( "ancestor", this ); resizeComp.removePropertyChangeListener( "ancestor", this );
Container cont = topDragComp.getParent(); resizeComp.remove( topDragComp );
cont.remove( topDragComp ); resizeComp.remove( bottomDragComp );
cont.remove( bottomDragComp ); resizeComp.remove( leftDragComp );
cont.remove( leftDragComp ); resizeComp.remove( rightDragComp );
cont.remove( rightDragComp );
} }
public void doLayout() { public void doLayout() {
@@ -120,7 +117,7 @@ public abstract class FlatWindowResizer
int y = 0; int y = 0;
int width = resizeComp.getWidth(); int width = resizeComp.getWidth();
int height = resizeComp.getHeight(); int height = resizeComp.getHeight();
if( width == 0 || height == 0 ) if( width <= 0 || height <= 0 )
return; return;
Insets resizeInsets = getResizeInsets(); Insets resizeInsets = getResizeInsets();
@@ -191,7 +188,7 @@ public abstract class FlatWindowResizer
protected abstract Dimension getWindowMinimumSize(); protected abstract Dimension getWindowMinimumSize();
protected abstract Dimension getWindowMaximumSize(); protected abstract Dimension getWindowMaximumSize();
protected void beginResizing( int direction ) {} protected void beginResizing( int resizeDir ) {}
protected void endResizing() {} protected void endResizing() {}
//---- interface PropertyChangeListener ---- //---- interface PropertyChangeListener ----
@@ -234,17 +231,45 @@ public abstract class FlatWindowResizer
{ {
protected Window window; protected Window window;
private final JComponent centerComp;
private final boolean limitResizeToScreenBounds; private final boolean limitResizeToScreenBounds;
public WindowResizer( JRootPane rootPane ) { public WindowResizer( JRootPane rootPane ) {
super( rootPane ); super( rootPane );
// Transparent "center" component that is made visible only while resizing window.
// It uses same cursor as the area where resize dragging started.
// This ensures that the cursor shape stays stable while dragging mouse
// into the window to make window smaller. Otherwise it would toggling between
// resize and standard cursor because the component layout is not updated
// fast enough and the mouse cursor is always updated from the component
// at the mouse location.
centerComp = new JPanel();
centerComp.setOpaque( false );
centerComp.setVisible( false );
rootPane.add( centerComp, 5 );
// On Linux, limit window resizing to screen bounds because otherwise // On Linux, limit window resizing to screen bounds because otherwise
// there would be a strange effect when the mouse is moved over a sidebar // there would be a strange effect when the mouse is moved over a sidebar
// while resizing and the opposite window side is also resized. // while resizing and the opposite window side is also resized.
limitResizeToScreenBounds = SystemInfo.isLinux; limitResizeToScreenBounds = SystemInfo.isLinux;
} }
@Override
public void uninstall() {
resizeComp.remove( centerComp );
super.uninstall();
}
@Override
public void doLayout() {
super.doLayout();
if( centerComp != null && centerComp.isVisible() )
centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() );
}
@Override @Override
protected void addNotify() { protected void addNotify() {
Container parent = resizeComp.getParent(); Container parent = resizeComp.getParent();
@@ -299,20 +324,17 @@ public abstract class FlatWindowResizer
@Override @Override
protected boolean limitToParentBounds() { protected boolean limitToParentBounds() {
return limitResizeToScreenBounds && window != null; return limitResizeToScreenBounds && window != null && window.getGraphicsConfiguration() != null;
} }
@Override @Override
protected Rectangle getParentBounds() { protected Rectangle getParentBounds() {
if( limitResizeToScreenBounds && window != null ) { GraphicsConfiguration gc = window.getGraphicsConfiguration();
GraphicsConfiguration gc = window.getGraphicsConfiguration(); Rectangle bounds = gc.getBounds();
Rectangle bounds = gc.getBounds(); Insets insets = window.getToolkit().getScreenInsets( gc );
Insets insets = window.getToolkit().getScreenInsets( gc ); return new Rectangle( bounds.x + insets.left, bounds.y + insets.top,
return new Rectangle( bounds.x + insets.left, bounds.y + insets.top, bounds.width - insets.left - insets.right,
bounds.width - insets.left - insets.right, bounds.height - insets.top - insets.bottom );
bounds.height - insets.top - insets.bottom );
}
return null;
} }
@Override @Override
@@ -346,6 +368,19 @@ public abstract class FlatWindowResizer
public void windowStateChanged( WindowEvent e ) { public void windowStateChanged( WindowEvent e ) {
updateVisibility(); updateVisibility();
} }
@Override
protected void beginResizing( int resizeDir ) {
centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() );
centerComp.setCursor( getPredefinedCursor( resizeDir ) );
centerComp.setVisible( true );
}
@Override
protected void endResizing() {
centerComp.setVisible( false );
centerComp.setCursor( null );
}
} }
//---- class InternalFrameResizer ----------------------------------------- //---- class InternalFrameResizer -----------------------------------------
@@ -427,7 +462,18 @@ public abstract class FlatWindowResizer
} }
@Override @Override
protected void beginResizing( int direction ) { protected void beginResizing( int resizeDir ) {
int direction = 0;
switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = NORTH; break;
case S_RESIZE_CURSOR: direction = SOUTH; break;
case W_RESIZE_CURSOR: direction = WEST; break;
case E_RESIZE_CURSOR: direction = EAST; break;
case NW_RESIZE_CURSOR: direction = NORTH_WEST; break;
case NE_RESIZE_CURSOR: direction = NORTH_EAST; break;
case SW_RESIZE_CURSOR: direction = SOUTH_WEST; break;
case SE_RESIZE_CURSOR: direction = SOUTH_EAST; break;
}
desktopManager.get().beginResizingFrame( getFrame(), direction ); desktopManager.get().beginResizingFrame( getFrame(), direction );
} }
@@ -535,18 +581,7 @@ debug*/
dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen; dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen;
dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen; dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen;
int direction = 0; beginResizing( resizeDir );
switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = NORTH; break;
case S_RESIZE_CURSOR: direction = SOUTH; break;
case W_RESIZE_CURSOR: direction = WEST; break;
case E_RESIZE_CURSOR: direction = EAST; break;
case NW_RESIZE_CURSOR: direction = NORTH_WEST; break;
case NE_RESIZE_CURSOR: direction = NORTH_EAST; break;
case SW_RESIZE_CURSOR: direction = SOUTH_WEST; break;
case SE_RESIZE_CURSOR: direction = SOUTH_EAST; break;
}
beginResizing( direction );
} }
@Override @Override

View File

@@ -0,0 +1,361 @@
/*
* Copyright 2025 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 static javax.swing.SwingConstants.*;
import java.awt.Color;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.IllegalComponentStateException;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import com.formdev.flatlaf.util.UIScale;
/**
* Rounded border for {@link Window}.
* Used for popups and for FlatLaf window decorations.
* <p>
* Border is painted only if window is not maximized (in both directions) and
* not in full screen mode. If maximized in one direction (vertically or horizontally),
* then a square border is painted.
* <p>
* Note: The rootpane of the window should have a {@link FlatEmptyBorder} with
* same insets as border width used in this class.
*
* @author Karl Tauber
* @since 3.6
*/
public class FlatWindowRoundedBorder
implements PropertyChangeListener, ComponentListener
{
protected final JRootPane rootPane;
protected final int borderCornerRadius;
protected final float borderWidth;
protected final Color borderColor;
protected final Shape cornerShape;
// edges
protected final RoundedBorderComponent northComp;
protected final RoundedBorderComponent southComp;
protected final RoundedBorderComponent westComp;
protected final RoundedBorderComponent eastComp;
// corners
protected final RoundedBorderComponent northWestComp;
protected final RoundedBorderComponent northEastComp;
protected final RoundedBorderComponent southWestComp;
protected final RoundedBorderComponent southEastComp;
protected Window window;
protected boolean windowIsRounded;
public FlatWindowRoundedBorder( JRootPane rootPane, int borderCornerRadius,
float borderWidth, Color borderColor )
{
this.rootPane = rootPane;
this.borderCornerRadius = borderCornerRadius;
this.borderWidth = borderWidth;
this.borderColor = borderColor;
// create shape used to paint rounded corners
cornerShape = createCornerShape();
// create edges
northComp = new RoundedBorderComponent( NORTH );
southComp = new RoundedBorderComponent( SOUTH );
westComp = new RoundedBorderComponent( WEST );
eastComp = new RoundedBorderComponent( EAST );
// create corners
northWestComp = new RoundedBorderComponent( NORTH_WEST );
northEastComp = new RoundedBorderComponent( NORTH_EAST );
southWestComp = new RoundedBorderComponent( SOUTH_WEST );
southEastComp = new RoundedBorderComponent( SOUTH_EAST );
// insert before layered pane
int insertIndex = rootPane.getComponentCount() - 1;
JLayeredPane layeredPane = rootPane.getLayeredPane();
for( int i = insertIndex; i >= 0; i-- ) {
if( rootPane.getComponent( insertIndex ) == layeredPane )
break;
}
// add edges
rootPane.add( northComp, insertIndex++ );
rootPane.add( southComp, insertIndex++ );
rootPane.add( westComp, insertIndex++ );
rootPane.add( eastComp, insertIndex++ );
// add corners
rootPane.add( northWestComp, insertIndex++ );
rootPane.add( northEastComp, insertIndex++ );
rootPane.add( southWestComp, insertIndex++ );
rootPane.add( southEastComp, insertIndex++ );
// add listeners
rootPane.addComponentListener( this );
rootPane.addPropertyChangeListener( "ancestor", this );
if( rootPane.isDisplayable() )
addNotify();
else
updateVisibility();
}
public void uninstall() {
removeNotify();
// remove listeners
rootPane.removeComponentListener( this );
rootPane.removePropertyChangeListener( "ancestor", this );
// remove edges
rootPane.remove( northComp );
rootPane.remove( southComp );
rootPane.remove( westComp );
rootPane.remove( eastComp );
// remove corners
rootPane.remove( northWestComp );
rootPane.remove( northEastComp );
rootPane.remove( southWestComp );
rootPane.remove( southEastComp );
}
public void doLayout() {
if( !northComp.isVisible() )
return;
int x = 0;
int y = 0;
int width = rootPane.getWidth();
int height = rootPane.getHeight();
if( width <= 0 || height <= 0 )
return;
// for layout, round-up scaled border width and radius to ensure that components are large enough
int lineWidth = (int) Math.ceil( UIScale.scale( borderWidth ) );
int cornerSize = (windowIsRounded && lineWidth > 0)
? (int) Math.ceil( UIScale.scale( (float) borderCornerRadius ) )
: 0;
int cornerSize2x = cornerSize * 2;
// edges
northComp.setBounds( x + cornerSize, y, width - cornerSize2x, lineWidth );
southComp.setBounds( x + cornerSize, y + height - lineWidth, width - cornerSize2x, lineWidth );
westComp.setBounds( x, y + cornerSize, lineWidth, height - cornerSize2x );
eastComp.setBounds( x + width - lineWidth, y + cornerSize, lineWidth, height - cornerSize2x );
// corners
northWestComp.setBounds( x, y, cornerSize, cornerSize );
northEastComp.setBounds( x + width - cornerSize, y, cornerSize, cornerSize );
southWestComp.setBounds( x, y + height - cornerSize, cornerSize, cornerSize );
southEastComp.setBounds( x + width - cornerSize, y + height - cornerSize, cornerSize, cornerSize );
}
protected void addNotify() {
Container parent = rootPane.getParent();
window = (parent instanceof Window) ? (Window) parent : null;
updateVisibility();
updateWindowShape();
doLayout();
}
protected void removeNotify() {
if( window != null ) {
window.setShape( null );
window = null;
}
updateVisibility();
}
protected void updateVisibility() {
boolean visible = needsBorder();
if( visible == northComp.isVisible() )
return;
// edges
northComp.setVisible( visible );
southComp.setVisible( visible );
westComp.setVisible( visible );
eastComp.setVisible( visible );
// corners
northWestComp.setVisible( visible );
northEastComp.setVisible( visible );
southWestComp.setVisible( visible );
southEastComp.setVisible( visible );
}
protected boolean needsBorder() {
if( window == null || FlatUIUtils.isFullScreen( window ) )
return false;
if( window instanceof Frame )
return (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != Frame.MAXIMIZED_BOTH;
return true;
}
protected void updateWindowShape() {
windowIsRounded = false;
if( window == null )
return;
if( !northComp.isVisible() ||
(window instanceof Frame && (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0) )
{
window.setShape( null );
return;
}
int arc = UIScale.scale( borderCornerRadius * 2 );
// use a slightly smaller arc for the shape so that at least parts of
// the antialiased arc outside are shown
arc -= 2;
if( arc > 0 ) {
try {
window.setShape( new RoundRectangle2D.Float( 0, 0,
rootPane.getWidth(), rootPane.getHeight(), arc, arc ) );
windowIsRounded = true;
} catch( IllegalComponentStateException | UnsupportedOperationException ex ) {
window.setShape( null );
}
} else
window.setShape( null );
}
protected Shape createCornerShape() {
float lineWidth = UIScale.scale( borderWidth );
int arc = UIScale.scale( borderCornerRadius * 2 );
int wh = arc * 3;
float innerArc = arc - (lineWidth * 2);
float innerWH = wh - (lineWidth * 2);
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new RoundRectangle2D.Float( 0, 0, wh, wh, arc, arc ), false );
path.append( new RoundRectangle2D.Float( lineWidth, lineWidth, innerWH, innerWH, innerArc, innerArc ), false );
Area area = new Area( path );
int cornerSize = (int) Math.ceil( UIScale.scale( (float) borderCornerRadius ) );
area.intersect( new Area( new Rectangle2D.Float( 0, 0, cornerSize, cornerSize ) ) );
return area;
}
//---- interface PropertyChangeListener ----
@Override
public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case "ancestor":
if( e.getNewValue() != null )
addNotify();
else
removeNotify();
break;
}
}
//---- interface ComponentListener ----
@Override
public void componentResized( ComponentEvent e ) {
updateVisibility();
updateWindowShape();
doLayout();
}
@Override public void componentMoved( ComponentEvent e ) {}
@Override public void componentShown( ComponentEvent e ) {}
@Override public void componentHidden( ComponentEvent e ) {}
//---- class RoundedBorderComponent ---------------------------------------
protected class RoundedBorderComponent
extends JComponent
{
private final int position;
protected RoundedBorderComponent( int position ) {
this.position = position;
}
@Override
public void paint( Graphics g ) {
Graphics2D g2 = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
float lineWidth = UIScale.scale( borderWidth );
/*debug
g.setColor( java.awt.Color.green );
g.drawRect( 0, 0, width - 1, height - 1 );
debug*/
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
g.setColor( borderColor );
switch( position ) {
case NORTH: g2.fill( new Rectangle2D.Float( 0, 0, width, lineWidth ) ); break;
case SOUTH: g2.fill( new Rectangle2D.Float( 0, height - lineWidth, width, lineWidth ) ); break;
case WEST: g2.fill( new Rectangle2D.Float( 0, 0, lineWidth, height ) ); break;
case EAST: g2.fill( new Rectangle2D.Float( width - lineWidth, 0, lineWidth, height ) ); break;
case NORTH_WEST:
g2.fill( cornerShape );
break;
case NORTH_EAST:
g2.translate( width, 0 );
g2.rotate( Math.toRadians( 90 ) );
g2.fill( cornerShape );
break;
case SOUTH_WEST:
g2.translate( 0, height );
g2.rotate( Math.toRadians( -90 ) );
g2.fill( cornerShape );
break;
case SOUTH_EAST:
g2.translate( width, height );
g2.rotate( Math.toRadians( 180 ) );
g2.fill( cornerShape );
break;
}
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
}
}
}

View File

@@ -33,6 +33,7 @@ import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.FontUIResource; import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.InsetsUIResource; import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.FlatSystemProperties;
/** /**
@@ -188,7 +189,9 @@ public class UIScale
// because even if we are on a HiDPI display it is not sure // because even if we are on a HiDPI display it is not sure
// that a larger font size is set by the current LaF // that a larger font size is set by the current LaF
// (e.g. can avoid large icons with small text) // (e.g. can avoid large icons with small text)
Font font = UIManager.getFont( "defaultFont" ); Font font = null;
if( UIManager.getLookAndFeel() instanceof FlatLaf )
font = UIManager.getFont( "defaultFont" );
if( font == null ) if( font == null )
font = UIManager.getFont( "Label.font" ); font = UIManager.getFont( "Label.font" );
@@ -244,6 +247,16 @@ public class UIScale
} }
private static float computeScaleFactor( Font font ) { private static float computeScaleFactor( Font font ) {
String customFontSizeDivider = System.getProperty( "flatlaf.uiScale.fontSizeDivider" );
if( customFontSizeDivider != null ) {
try {
float fontSizeDivider = Math.max( Integer.parseInt( customFontSizeDivider ), 10 );
return font.getSize() / fontSizeDivider;
} catch( NumberFormatException ex ) {
// ignore
}
}
// default font size // default font size
float fontSizeDivider = 12f; float fontSizeDivider = 12f;

View File

@@ -246,7 +246,6 @@ PasswordField.revealIconColor = @foreground
#---- Popup ---- #---- Popup ----
[mac]Popup.roundedBorderWidth = 1
Popup.dropShadowColor = #000 Popup.dropShadowColor = #000
Popup.dropShadowOpacity = 0.25 Popup.dropShadowOpacity = 0.25

View File

@@ -289,7 +289,7 @@ ComboBox.popupInsets = 0,0,0,0
ComboBox.selectionInsets = 0,0,0,0 ComboBox.selectionInsets = 0,0,0,0
ComboBox.selectionArc = 0 ComboBox.selectionArc = 0
ComboBox.borderCornerRadius = $Popup.borderCornerRadius ComboBox.borderCornerRadius = $Popup.borderCornerRadius
[mac]ComboBox.roundedBorderWidth = $Popup.roundedBorderWidth ComboBox.roundedBorderWidth = $Popup.roundedBorderWidth
#---- Component ---- #---- Component ----
@@ -506,7 +506,7 @@ PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
#---- Popup ---- #---- Popup ----
Popup.borderCornerRadius = 4 Popup.borderCornerRadius = 4
[mac]Popup.roundedBorderWidth = 0 Popup.roundedBorderWidth = 1
Popup.dropShadowPainted = true Popup.dropShadowPainted = true
Popup.dropShadowInsets = -4,-4,4,4 Popup.dropShadowInsets = -4,-4,4,4
@@ -516,7 +516,7 @@ Popup.dropShadowInsets = -4,-4,4,4
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
PopupMenu.borderInsets = 4,1,4,1 PopupMenu.borderInsets = 4,1,4,1
PopupMenu.borderCornerRadius = $Popup.borderCornerRadius PopupMenu.borderCornerRadius = $Popup.borderCornerRadius
[mac]PopupMenu.roundedBorderWidth = $Popup.roundedBorderWidth PopupMenu.roundedBorderWidth = $Popup.roundedBorderWidth
PopupMenu.background = @menuBackground PopupMenu.background = @menuBackground
PopupMenu.scrollArrowColor = @buttonArrowColor PopupMenu.scrollArrowColor = @buttonArrowColor
@@ -913,7 +913,7 @@ ToolTipManager.enableToolTipMode = activeApplication
#---- ToolTip ---- #---- ToolTip ----
ToolTip.borderCornerRadius = $Popup.borderCornerRadius ToolTip.borderCornerRadius = $Popup.borderCornerRadius
[mac]ToolTip.roundedBorderWidth = $Popup.roundedBorderWidth ToolTip.roundedBorderWidth = $Popup.roundedBorderWidth
#---- Tree ---- #---- Tree ----
@@ -934,6 +934,7 @@ Tree.rendererMargins = 1,2,1,2
Tree.selectionInsets = 0,0,0,0 Tree.selectionInsets = 0,0,0,0
Tree.selectionArc = 0 Tree.selectionArc = 0
Tree.wideSelection = true Tree.wideSelection = true
Tree.wideCellRenderer = false
Tree.repaintWholeRow = true Tree.repaintWholeRow = true
Tree.paintLines = false Tree.paintLines = false
Tree.showCellFocusIndicator = false Tree.showCellFocusIndicator = false

View File

@@ -253,6 +253,7 @@ PasswordField.revealIconColor = tint(@foreground,40%)
#---- Popup ---- #---- Popup ----
[mac]Popup.roundedBorderWidth = 0
Popup.dropShadowColor = #000 Popup.dropShadowColor = #000
Popup.dropShadowOpacity = 0.15 Popup.dropShadowOpacity = 0.15

View File

@@ -0,0 +1,123 @@
/*
* 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 static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Locale;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.View;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* @author Karl Tauber
*/
public class TestFlatHTML
{
private final String body = "some <small>small</small> text";
private final String bodyInBody = "<body>" + body + "</body>";
private final String bodyPlain = "some small text";
@BeforeAll
static void setup() {
TestUtils.setup( false );
TestUtils.scaleFont( 2 );
}
@AfterAll
static void cleanup() {
TestUtils.cleanup();
}
@Test
void simple() {
testHtmlBaseSize( "<html>${BASE_SIZE_IN_HEAD}" + body + "</html>", bodyPlain );
testHtmlBaseSize( "<html>${BASE_SIZE_IN_HEAD}" + bodyInBody + "</html>", bodyPlain );
}
@Test
void htmlWithHeadTag() {
testHtmlBaseSize( "<html><head>${BASE_SIZE}<title>test</title><head>" + body + "</html>", bodyPlain );
testHtmlBaseSize( "<html><head>${BASE_SIZE}<title>test</title><head>" + bodyInBody + "</html>", bodyPlain );
testHtmlBaseSize( "<html><head id=\"abc\">${BASE_SIZE}<title>test</title><head>" + body + "</html>", bodyPlain );
testHtmlBaseSize( "<html><head id=\"abc\">${BASE_SIZE}<title>test</title><head>" + bodyInBody + "</html>", bodyPlain );
}
@Test
void htmlWithStyleTag() {
testHtmlBaseSize( "<html>${BASE_SIZE}<style>body { color: #f00; }</style>" + bodyInBody + "</html>", bodyPlain );
testHtmlBaseSize( "<html>${BASE_SIZE}<style>body { color: #f00; }</style><h1>header1</h1>" + body + "</html>", "header1\n" + bodyPlain );
testHtmlBaseSize( "<html>${BASE_SIZE}<style type='text/css'>body { color: #f00; }</style>" + bodyInBody + "</html>", bodyPlain );
testHtmlBaseSize( "<html>${BASE_SIZE}<style type='text/css'>body { color: #f00; }</style><h1>header1</h1>" + body + "</html>", "header1\n" + bodyPlain );
}
@Test
void htmlOnComponentWithNullFont() {
assertDoesNotThrow( () -> {
JLabel label = new JLabel();
label.setFont( null );
label.setText( "<html>foo<br>bar</html>" );
} );
}
private void testHtmlBaseSize( String html, String expectedPlain ) {
testHtmlBaseSizeImpl( html, expectedPlain );
testHtmlBaseSizeImpl( html.toUpperCase( Locale.ENGLISH ), expectedPlain.toUpperCase( Locale.ENGLISH ) );
}
private void testHtmlBaseSizeImpl( String html, String expectedPlain ) {
String baseSize = "<style>BASE_SIZE " + UIManager.getFont( "Label.font" ).getSize() + "</style>";
String baseSizeInHead = "<head>" + baseSize + "</head>";
String expectedHtml = html.replace( "${BASE_SIZE}", baseSize ).replace( "${BASE_SIZE_IN_HEAD}", baseSizeInHead );
html = html.replace( "${BASE_SIZE}", "" ).replace( "${BASE_SIZE_IN_HEAD}", "" );
testHtml( html, expectedHtml, expectedPlain );
}
private void testHtml( String html, String expectedHtml, String expectedPlain ) {
FlatHTML.testUpdateRenderer = (c, newHtml) -> {
assertEquals( expectedHtml, newHtml );
assertEquals( expectedPlain, getPlainText( c ) );
};
new JLabel( html );
FlatHTML.testUpdateRenderer = null;
}
private String getPlainText( JComponent c ) {
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
if( view == null )
return null;
Document doc = view.getDocument();
try {
return doc.getText( 0, doc.getLength() ).trim();
} catch( BadLocationException ex ) {
ex.printStackTrace();
return null;
}
}
}

View File

@@ -270,6 +270,7 @@ public class TestFlatStyleableInfo
"selectionForeground", Color.class, "selectionForeground", Color.class,
"selectionInactiveBackground", Color.class, "selectionInactiveBackground", Color.class,
"selectionInactiveForeground", Color.class, "selectionInactiveForeground", Color.class,
"alternateRowColor", Color.class,
"selectionInsets", Insets.class, "selectionInsets", Insets.class,
"selectionArc", int.class, "selectionArc", int.class,
@@ -517,6 +518,8 @@ public class TestFlatStyleableInfo
"icon.borderWidth", float.class, "icon.borderWidth", float.class,
"icon.selectedBorderWidth", float.class, "icon.selectedBorderWidth", float.class,
"icon.disabledSelectedBorderWidth", float.class, "icon.disabledSelectedBorderWidth", float.class,
"icon.indeterminateBorderWidth", float.class,
"icon.disabledIndeterminateBorderWidth", float.class,
"icon.arc", int.class, "icon.arc", int.class,
// enabled // enabled
@@ -525,6 +528,9 @@ public class TestFlatStyleableInfo
"icon.selectedBorderColor", Color.class, "icon.selectedBorderColor", Color.class,
"icon.selectedBackground", Color.class, "icon.selectedBackground", Color.class,
"icon.checkmarkColor", Color.class, "icon.checkmarkColor", Color.class,
"icon.indeterminateBorderColor", Color.class,
"icon.indeterminateBackground", Color.class,
"icon.indeterminateCheckmarkColor", Color.class,
// disabled // disabled
"icon.disabledBorderColor", Color.class, "icon.disabledBorderColor", Color.class,
@@ -532,6 +538,9 @@ public class TestFlatStyleableInfo
"icon.disabledSelectedBorderColor", Color.class, "icon.disabledSelectedBorderColor", Color.class,
"icon.disabledSelectedBackground", Color.class, "icon.disabledSelectedBackground", Color.class,
"icon.disabledCheckmarkColor", Color.class, "icon.disabledCheckmarkColor", Color.class,
"icon.disabledIndeterminateBorderColor", Color.class,
"icon.disabledIndeterminateBackground", Color.class,
"icon.disabledIndeterminateCheckmarkColor", Color.class,
// focused // focused
"icon.focusedBorderColor", Color.class, "icon.focusedBorderColor", Color.class,
@@ -539,6 +548,9 @@ public class TestFlatStyleableInfo
"icon.focusedSelectedBorderColor", Color.class, "icon.focusedSelectedBorderColor", Color.class,
"icon.focusedSelectedBackground", Color.class, "icon.focusedSelectedBackground", Color.class,
"icon.focusedCheckmarkColor", Color.class, "icon.focusedCheckmarkColor", Color.class,
"icon.focusedIndeterminateBorderColor", Color.class,
"icon.focusedIndeterminateBackground", Color.class,
"icon.focusedIndeterminateCheckmarkColor", Color.class,
// hover // hover
"icon.hoverBorderColor", Color.class, "icon.hoverBorderColor", Color.class,
@@ -546,13 +558,19 @@ public class TestFlatStyleableInfo
"icon.hoverSelectedBorderColor", Color.class, "icon.hoverSelectedBorderColor", Color.class,
"icon.hoverSelectedBackground", Color.class, "icon.hoverSelectedBackground", Color.class,
"icon.hoverCheckmarkColor", Color.class, "icon.hoverCheckmarkColor", Color.class,
"icon.hoverIndeterminateBorderColor", Color.class,
"icon.hoverIndeterminateBackground", Color.class,
"icon.hoverIndeterminateCheckmarkColor", Color.class,
// pressed // pressed
"icon.pressedBorderColor", Color.class, "icon.pressedBorderColor", Color.class,
"icon.pressedBackground", Color.class, "icon.pressedBackground", Color.class,
"icon.pressedSelectedBorderColor", Color.class, "icon.pressedSelectedBorderColor", Color.class,
"icon.pressedSelectedBackground", Color.class, "icon.pressedSelectedBackground", Color.class,
"icon.pressedCheckmarkColor", Color.class "icon.pressedCheckmarkColor", Color.class,
"icon.pressedIndeterminateBorderColor", Color.class,
"icon.pressedIndeterminateBackground", Color.class,
"icon.pressedIndeterminateCheckmarkColor", Color.class
); );
} }
@@ -965,9 +983,11 @@ public class TestFlatStyleableInfo
"selectionInactiveBackground", Color.class, "selectionInactiveBackground", Color.class,
"selectionInactiveForeground", Color.class, "selectionInactiveForeground", Color.class,
"selectionBorderColor", Color.class, "selectionBorderColor", Color.class,
"alternateRowColor", Color.class,
"selectionInsets", Insets.class, "selectionInsets", Insets.class,
"selectionArc", int.class, "selectionArc", int.class,
"wideSelection", boolean.class, "wideSelection", boolean.class,
"wideCellRenderer", boolean.class,
"showCellFocusIndicator", boolean.class, "showCellFocusIndicator", boolean.class,
"paintSelection", boolean.class, "paintSelection", boolean.class,
@@ -1144,6 +1164,8 @@ public class TestFlatStyleableInfo
"borderWidth", float.class, "borderWidth", float.class,
"selectedBorderWidth", float.class, "selectedBorderWidth", float.class,
"disabledSelectedBorderWidth", float.class, "disabledSelectedBorderWidth", float.class,
"indeterminateBorderWidth", float.class,
"disabledIndeterminateBorderWidth", float.class,
"arc", int.class, "arc", int.class,
// enabled // enabled
@@ -1152,6 +1174,9 @@ public class TestFlatStyleableInfo
"selectedBorderColor", Color.class, "selectedBorderColor", Color.class,
"selectedBackground", Color.class, "selectedBackground", Color.class,
"checkmarkColor", Color.class, "checkmarkColor", Color.class,
"indeterminateBorderColor", Color.class,
"indeterminateBackground", Color.class,
"indeterminateCheckmarkColor", Color.class,
// disabled // disabled
"disabledBorderColor", Color.class, "disabledBorderColor", Color.class,
@@ -1159,6 +1184,9 @@ public class TestFlatStyleableInfo
"disabledSelectedBorderColor", Color.class, "disabledSelectedBorderColor", Color.class,
"disabledSelectedBackground", Color.class, "disabledSelectedBackground", Color.class,
"disabledCheckmarkColor", Color.class, "disabledCheckmarkColor", Color.class,
"disabledIndeterminateBorderColor", Color.class,
"disabledIndeterminateBackground", Color.class,
"disabledIndeterminateCheckmarkColor", Color.class,
// focused // focused
"focusedBorderColor", Color.class, "focusedBorderColor", Color.class,
@@ -1166,6 +1194,9 @@ public class TestFlatStyleableInfo
"focusedSelectedBorderColor", Color.class, "focusedSelectedBorderColor", Color.class,
"focusedSelectedBackground", Color.class, "focusedSelectedBackground", Color.class,
"focusedCheckmarkColor", Color.class, "focusedCheckmarkColor", Color.class,
"focusedIndeterminateBorderColor", Color.class,
"focusedIndeterminateBackground", Color.class,
"focusedIndeterminateCheckmarkColor", Color.class,
// hover // hover
"hoverBorderColor", Color.class, "hoverBorderColor", Color.class,
@@ -1173,13 +1204,19 @@ public class TestFlatStyleableInfo
"hoverSelectedBorderColor", Color.class, "hoverSelectedBorderColor", Color.class,
"hoverSelectedBackground", Color.class, "hoverSelectedBackground", Color.class,
"hoverCheckmarkColor", Color.class, "hoverCheckmarkColor", Color.class,
"hoverIndeterminateBorderColor", Color.class,
"hoverIndeterminateBackground", Color.class,
"hoverIndeterminateCheckmarkColor", Color.class,
// pressed // pressed
"pressedBorderColor", Color.class, "pressedBorderColor", Color.class,
"pressedBackground", Color.class, "pressedBackground", Color.class,
"pressedSelectedBorderColor", Color.class, "pressedSelectedBorderColor", Color.class,
"pressedSelectedBackground", Color.class, "pressedSelectedBackground", Color.class,
"pressedCheckmarkColor", Color.class "pressedCheckmarkColor", Color.class,
"pressedIndeterminateBorderColor", Color.class,
"pressedIndeterminateBackground", Color.class,
"pressedIndeterminateCheckmarkColor", Color.class
); );
} }

View File

@@ -370,6 +370,7 @@ public class TestFlatStyleableValue
testColor( c, ui, "selectionForeground", 0x123456 ); testColor( c, ui, "selectionForeground", 0x123456 );
testColor( c, ui, "selectionInactiveBackground", 0x123456 ); testColor( c, ui, "selectionInactiveBackground", 0x123456 );
testColor( c, ui, "selectionInactiveForeground", 0x123456 ); testColor( c, ui, "selectionInactiveForeground", 0x123456 );
testColor( c, ui, "alternateRowColor", 0x123456 );
testInsets( c, ui, "selectionInsets", 1,2,3,4 ); testInsets( c, ui, "selectionInsets", 1,2,3,4 );
testInteger( c, ui, "selectionArc", 123 ); testInteger( c, ui, "selectionArc", 123 );
@@ -938,9 +939,11 @@ public class TestFlatStyleableValue
testColor( c, ui, "selectionInactiveBackground", 0x123456 ); testColor( c, ui, "selectionInactiveBackground", 0x123456 );
testColor( c, ui, "selectionInactiveForeground", 0x123456 ); testColor( c, ui, "selectionInactiveForeground", 0x123456 );
testColor( c, ui, "selectionBorderColor", 0x123456 ); testColor( c, ui, "selectionBorderColor", 0x123456 );
testColor( c, ui, "alternateRowColor", 0x123456 );
testInsets( c, ui, "selectionInsets", 1,2,3,4 ); testInsets( c, ui, "selectionInsets", 1,2,3,4 );
testInteger( c, ui, "selectionArc", 123 ); testInteger( c, ui, "selectionArc", 123 );
testBoolean( c, ui, "wideSelection", true ); testBoolean( c, ui, "wideSelection", true );
testBoolean( c, ui, "wideCellRenderer", true );
testBoolean( c, ui, "showCellFocusIndicator", true ); testBoolean( c, ui, "showCellFocusIndicator", true );
testBoolean( c, ui, "paintSelection", false ); testBoolean( c, ui, "paintSelection", false );
@@ -1146,6 +1149,8 @@ public class TestFlatStyleableValue
testValue( icon, "borderWidth", 1.5f ); testValue( icon, "borderWidth", 1.5f );
testValue( icon, "selectedBorderWidth", 1.5f ); testValue( icon, "selectedBorderWidth", 1.5f );
testValue( icon, "disabledSelectedBorderWidth", 1.5f ); testValue( icon, "disabledSelectedBorderWidth", 1.5f );
testValue( icon, "indeterminateBorderWidth", 1.5f );
testValue( icon, "disabledIndeterminateBorderWidth", 1.5f );
testValue( icon, "arc", 5 ); testValue( icon, "arc", 5 );
// enabled // enabled
@@ -1154,6 +1159,9 @@ public class TestFlatStyleableValue
testValue( icon, "selectedBorderColor", Color.WHITE ); testValue( icon, "selectedBorderColor", Color.WHITE );
testValue( icon, "selectedBackground", Color.WHITE ); testValue( icon, "selectedBackground", Color.WHITE );
testValue( icon, "checkmarkColor", Color.WHITE ); testValue( icon, "checkmarkColor", Color.WHITE );
testValue( icon, "indeterminateBorderColor", Color.WHITE );
testValue( icon, "indeterminateBackground", Color.WHITE );
testValue( icon, "indeterminateCheckmarkColor", Color.WHITE );
// disabled // disabled
testValue( icon, "disabledBorderColor", Color.WHITE ); testValue( icon, "disabledBorderColor", Color.WHITE );
@@ -1161,6 +1169,9 @@ public class TestFlatStyleableValue
testValue( icon, "disabledSelectedBorderColor", Color.WHITE ); testValue( icon, "disabledSelectedBorderColor", Color.WHITE );
testValue( icon, "disabledSelectedBackground", Color.WHITE ); testValue( icon, "disabledSelectedBackground", Color.WHITE );
testValue( icon, "disabledCheckmarkColor", Color.WHITE ); testValue( icon, "disabledCheckmarkColor", Color.WHITE );
testValue( icon, "disabledIndeterminateBorderColor", Color.WHITE );
testValue( icon, "disabledIndeterminateBackground", Color.WHITE );
testValue( icon, "disabledIndeterminateCheckmarkColor", Color.WHITE );
// focused // focused
testValue( icon, "focusedBorderColor", Color.WHITE ); testValue( icon, "focusedBorderColor", Color.WHITE );
@@ -1168,6 +1179,9 @@ public class TestFlatStyleableValue
testValue( icon, "focusedSelectedBorderColor", Color.WHITE ); testValue( icon, "focusedSelectedBorderColor", Color.WHITE );
testValue( icon, "focusedSelectedBackground", Color.WHITE ); testValue( icon, "focusedSelectedBackground", Color.WHITE );
testValue( icon, "focusedCheckmarkColor", Color.WHITE ); testValue( icon, "focusedCheckmarkColor", Color.WHITE );
testValue( icon, "focusedIndeterminateBorderColor", Color.WHITE );
testValue( icon, "focusedIndeterminateBackground", Color.WHITE );
testValue( icon, "focusedIndeterminateCheckmarkColor", Color.WHITE );
// hover // hover
testValue( icon, "hoverBorderColor", Color.WHITE ); testValue( icon, "hoverBorderColor", Color.WHITE );
@@ -1175,6 +1189,9 @@ public class TestFlatStyleableValue
testValue( icon, "hoverSelectedBorderColor", Color.WHITE ); testValue( icon, "hoverSelectedBorderColor", Color.WHITE );
testValue( icon, "hoverSelectedBackground", Color.WHITE ); testValue( icon, "hoverSelectedBackground", Color.WHITE );
testValue( icon, "hoverCheckmarkColor", Color.WHITE ); testValue( icon, "hoverCheckmarkColor", Color.WHITE );
testValue( icon, "hoverIndeterminateBorderColor", Color.WHITE );
testValue( icon, "hoverIndeterminateBackground", Color.WHITE );
testValue( icon, "hoverIndeterminateCheckmarkColor", Color.WHITE );
// pressed // pressed
testValue( icon, "pressedBorderColor", Color.WHITE ); testValue( icon, "pressedBorderColor", Color.WHITE );
@@ -1182,6 +1199,9 @@ public class TestFlatStyleableValue
testValue( icon, "pressedSelectedBorderColor", Color.WHITE ); testValue( icon, "pressedSelectedBorderColor", Color.WHITE );
testValue( icon, "pressedSelectedBackground", Color.WHITE ); testValue( icon, "pressedSelectedBackground", Color.WHITE );
testValue( icon, "pressedCheckmarkColor", Color.WHITE ); testValue( icon, "pressedCheckmarkColor", Color.WHITE );
testValue( icon, "pressedIndeterminateBorderColor", Color.WHITE );
testValue( icon, "pressedIndeterminateBackground", Color.WHITE );
testValue( icon, "pressedIndeterminateCheckmarkColor", Color.WHITE );
} }
@Test @Test

View File

@@ -433,6 +433,7 @@ public class TestFlatStyling
ui.applyStyle( "selectionForeground: #fff" ); ui.applyStyle( "selectionForeground: #fff" );
ui.applyStyle( "selectionInactiveBackground: #fff" ); ui.applyStyle( "selectionInactiveBackground: #fff" );
ui.applyStyle( "selectionInactiveForeground: #fff" ); ui.applyStyle( "selectionInactiveForeground: #fff" );
ui.applyStyle( "alternateRowColor: #fff" );
ui.applyStyle( "selectionInsets: 1,2,3,4" ); ui.applyStyle( "selectionInsets: 1,2,3,4" );
ui.applyStyle( "selectionArc: 8" ); ui.applyStyle( "selectionArc: 8" );
@@ -1187,9 +1188,11 @@ public class TestFlatStyling
ui.applyStyle( "selectionInactiveBackground: #fff" ); ui.applyStyle( "selectionInactiveBackground: #fff" );
ui.applyStyle( "selectionInactiveForeground: #fff" ); ui.applyStyle( "selectionInactiveForeground: #fff" );
ui.applyStyle( "selectionBorderColor: #fff" ); ui.applyStyle( "selectionBorderColor: #fff" );
ui.applyStyle( "alternateRowColor: #fff" );
ui.applyStyle( "selectionInsets: 1,2,3,4" ); ui.applyStyle( "selectionInsets: 1,2,3,4" );
ui.applyStyle( "selectionArc: 8" ); ui.applyStyle( "selectionArc: 8" );
ui.applyStyle( "wideSelection: true" ); ui.applyStyle( "wideSelection: true" );
ui.applyStyle( "wideCellRenderer: true" );
ui.applyStyle( "showCellFocusIndicator: true" ); ui.applyStyle( "showCellFocusIndicator: true" );
ui.applyStyle( "paintSelection: false" ); ui.applyStyle( "paintSelection: false" );
@@ -1388,6 +1391,8 @@ public class TestFlatStyling
icon.applyStyleProperty( "borderWidth", 1.5f ); icon.applyStyleProperty( "borderWidth", 1.5f );
icon.applyStyleProperty( "selectedBorderWidth", 1.5f ); icon.applyStyleProperty( "selectedBorderWidth", 1.5f );
icon.applyStyleProperty( "disabledSelectedBorderWidth", 1.5f ); icon.applyStyleProperty( "disabledSelectedBorderWidth", 1.5f );
icon.applyStyleProperty( "indeterminateBorderWidth", 1.5f );
icon.applyStyleProperty( "disabledIndeterminateBorderWidth", 1.5f );
icon.applyStyleProperty( "arc", 5 ); icon.applyStyleProperty( "arc", 5 );
// enabled // enabled
@@ -1396,6 +1401,9 @@ public class TestFlatStyling
icon.applyStyleProperty( "selectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "selectedBorderColor", Color.WHITE );
icon.applyStyleProperty( "selectedBackground", Color.WHITE ); icon.applyStyleProperty( "selectedBackground", Color.WHITE );
icon.applyStyleProperty( "checkmarkColor", Color.WHITE ); icon.applyStyleProperty( "checkmarkColor", Color.WHITE );
icon.applyStyleProperty( "indeterminateBorderColor", Color.WHITE );
icon.applyStyleProperty( "indeterminateBackground", Color.WHITE );
icon.applyStyleProperty( "indeterminateCheckmarkColor", Color.WHITE );
// disabled // disabled
icon.applyStyleProperty( "disabledBorderColor", Color.WHITE ); icon.applyStyleProperty( "disabledBorderColor", Color.WHITE );
@@ -1403,6 +1411,9 @@ public class TestFlatStyling
icon.applyStyleProperty( "disabledSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "disabledSelectedBorderColor", Color.WHITE );
icon.applyStyleProperty( "disabledSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "disabledSelectedBackground", Color.WHITE );
icon.applyStyleProperty( "disabledCheckmarkColor", Color.WHITE ); icon.applyStyleProperty( "disabledCheckmarkColor", Color.WHITE );
icon.applyStyleProperty( "disabledIndeterminateBorderColor", Color.WHITE );
icon.applyStyleProperty( "disabledIndeterminateBackground", Color.WHITE );
icon.applyStyleProperty( "disabledIndeterminateCheckmarkColor", Color.WHITE );
// focused // focused
icon.applyStyleProperty( "focusedBorderColor", Color.WHITE ); icon.applyStyleProperty( "focusedBorderColor", Color.WHITE );
@@ -1410,6 +1421,9 @@ public class TestFlatStyling
icon.applyStyleProperty( "focusedSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "focusedSelectedBorderColor", Color.WHITE );
icon.applyStyleProperty( "focusedSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "focusedSelectedBackground", Color.WHITE );
icon.applyStyleProperty( "focusedCheckmarkColor", Color.WHITE ); icon.applyStyleProperty( "focusedCheckmarkColor", Color.WHITE );
icon.applyStyleProperty( "focusedIndeterminateBorderColor", Color.WHITE );
icon.applyStyleProperty( "focusedIndeterminateBackground", Color.WHITE );
icon.applyStyleProperty( "focusedIndeterminateCheckmarkColor", Color.WHITE );
// hover // hover
icon.applyStyleProperty( "hoverBorderColor", Color.WHITE ); icon.applyStyleProperty( "hoverBorderColor", Color.WHITE );
@@ -1417,6 +1431,9 @@ public class TestFlatStyling
icon.applyStyleProperty( "hoverSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "hoverSelectedBorderColor", Color.WHITE );
icon.applyStyleProperty( "hoverSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "hoverSelectedBackground", Color.WHITE );
icon.applyStyleProperty( "hoverCheckmarkColor", Color.WHITE ); icon.applyStyleProperty( "hoverCheckmarkColor", Color.WHITE );
icon.applyStyleProperty( "hoverIndeterminateBorderColor", Color.WHITE );
icon.applyStyleProperty( "hoverIndeterminateBackground", Color.WHITE );
icon.applyStyleProperty( "hoverIndeterminateCheckmarkColor", Color.WHITE );
// pressed // pressed
icon.applyStyleProperty( "pressedBorderColor", Color.WHITE ); icon.applyStyleProperty( "pressedBorderColor", Color.WHITE );
@@ -1424,6 +1441,9 @@ public class TestFlatStyling
icon.applyStyleProperty( "pressedSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "pressedSelectedBorderColor", Color.WHITE );
icon.applyStyleProperty( "pressedSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "pressedSelectedBackground", Color.WHITE );
icon.applyStyleProperty( "pressedCheckmarkColor", Color.WHITE ); icon.applyStyleProperty( "pressedCheckmarkColor", Color.WHITE );
icon.applyStyleProperty( "pressedIndeterminateBorderColor", Color.WHITE );
icon.applyStyleProperty( "pressedIndeterminateBackground", Color.WHITE );
icon.applyStyleProperty( "pressedIndeterminateCheckmarkColor", Color.WHITE );
} }
@Test @Test

View File

@@ -6,7 +6,7 @@
# when the Demo window is activated. # when the Demo window is activated.
# base theme (light, dark, intellij or darcula) # base theme (light, dark, intellij, darcula, maclight or macdark)
@baseTheme = light @baseTheme = light
# add you theme defaults here # add you theme defaults here

View File

@@ -277,22 +277,22 @@ class BasicComponentsPanel
//---- button5 ---- //---- button5 ----
button5.setText("Square"); button5.setText("Square");
button5.putClientProperty("JButton.buttonType", "square"); button5.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_SQUARE);
add(button5, "cell 3 1"); add(button5, "cell 3 1");
//---- button6 ---- //---- button6 ----
button6.setText("Round"); button6.setText("Round");
button6.putClientProperty("JButton.buttonType", "roundRect"); button6.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_ROUND_RECT);
add(button6, "cell 4 1"); add(button6, "cell 4 1");
//---- button3 ---- //---- button3 ----
button3.setText("Help"); button3.setText("Help");
button3.putClientProperty("JButton.buttonType", "help"); button3.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(button3, "cell 4 1"); add(button3, "cell 4 1");
//---- button4 ---- //---- button4 ----
button4.setText("Help"); button4.setText("Help");
button4.putClientProperty("JButton.buttonType", "help"); button4.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
button4.setEnabled(false); button4.setEnabled(false);
add(button4, "cell 4 1"); add(button4, "cell 4 1");
@@ -432,7 +432,7 @@ class BasicComponentsPanel
//---- comboBox6 ---- //---- comboBox6 ----
comboBox6.setEditable(true); comboBox6.setEditable(true);
comboBox6.putClientProperty("JTextField.placeholderText", "Placeholder"); comboBox6.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "Placeholder");
add(comboBox6, "cell 5 5,growx"); add(comboBox6, "cell 5 5,growx");
//---- textFieldLabel ---- //---- textFieldLabel ----
@@ -463,7 +463,7 @@ class BasicComponentsPanel
add(textField4, "cell 4 6,growx"); add(textField4, "cell 4 6,growx");
//---- textField6 ---- //---- textField6 ----
textField6.putClientProperty("JTextField.placeholderText", "Placeholder"); textField6.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "Placeholder");
add(textField6, "cell 5 6,growx"); add(textField6, "cell 5 6,growx");
//---- formattedTextFieldLabel ---- //---- formattedTextFieldLabel ----
@@ -494,7 +494,7 @@ class BasicComponentsPanel
add(formattedTextField4, "cell 4 7,growx"); add(formattedTextField4, "cell 4 7,growx");
//---- formattedTextField5 ---- //---- formattedTextField5 ----
formattedTextField5.putClientProperty("JTextField.placeholderText", "Placeholder"); formattedTextField5.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "Placeholder");
add(formattedTextField5, "cell 5 7,growx"); add(formattedTextField5, "cell 5 7,growx");
//---- passwordFieldLabel ---- //---- passwordFieldLabel ----
@@ -522,7 +522,7 @@ class BasicComponentsPanel
add(passwordField4, "cell 4 8,growx"); add(passwordField4, "cell 4 8,growx");
//---- passwordField5 ---- //---- passwordField5 ----
passwordField5.putClientProperty("JTextField.placeholderText", "Placeholder"); passwordField5.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "Placeholder");
add(passwordField5, "cell 5 8,growx"); add(passwordField5, "cell 5 8,growx");
//---- textAreaLabel ---- //---- textAreaLabel ----
@@ -703,11 +703,11 @@ class BasicComponentsPanel
add(errorHintsLabel, "cell 0 12"); add(errorHintsLabel, "cell 0 12");
//---- errorHintsTextField ---- //---- errorHintsTextField ----
errorHintsTextField.putClientProperty("JComponent.outline", "error"); errorHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
add(errorHintsTextField, "cell 1 12,growx"); add(errorHintsTextField, "cell 1 12,growx");
//---- errorHintsComboBox ---- //---- errorHintsComboBox ----
errorHintsComboBox.putClientProperty("JComponent.outline", "error"); errorHintsComboBox.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
errorHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] { errorHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"Editable" "Editable"
})); }));
@@ -715,7 +715,7 @@ class BasicComponentsPanel
add(errorHintsComboBox, "cell 2 12,growx"); add(errorHintsComboBox, "cell 2 12,growx");
//---- errorHintsSpinner ---- //---- errorHintsSpinner ----
errorHintsSpinner.putClientProperty("JComponent.outline", "error"); errorHintsSpinner.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
add(errorHintsSpinner, "cell 3 12,growx"); add(errorHintsSpinner, "cell 3 12,growx");
//---- warningHintsLabel ---- //---- warningHintsLabel ----
@@ -723,18 +723,18 @@ class BasicComponentsPanel
add(warningHintsLabel, "cell 0 13"); add(warningHintsLabel, "cell 0 13");
//---- warningHintsTextField ---- //---- warningHintsTextField ----
warningHintsTextField.putClientProperty("JComponent.outline", "warning"); warningHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
add(warningHintsTextField, "cell 1 13,growx"); add(warningHintsTextField, "cell 1 13,growx");
//---- warningHintsComboBox ---- //---- warningHintsComboBox ----
warningHintsComboBox.putClientProperty("JComponent.outline", "warning"); warningHintsComboBox.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
warningHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] { warningHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"Not editable" "Not editable"
})); }));
add(warningHintsComboBox, "cell 2 13,growx"); add(warningHintsComboBox, "cell 2 13,growx");
//---- warningHintsSpinner ---- //---- warningHintsSpinner ----
warningHintsSpinner.putClientProperty("JComponent.outline", "warning"); warningHintsSpinner.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
add(warningHintsSpinner, "cell 3 13,growx"); add(warningHintsSpinner, "cell 3 13,growx");
//---- iconsLabel ---- //---- iconsLabel ----
@@ -765,53 +765,53 @@ class BasicComponentsPanel
//---- h00Label ---- //---- h00Label ----
h00Label.setText("H00"); h00Label.setText("H00");
h00Label.putClientProperty("FlatLaf.styleClass", "h00"); h00Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h00");
add(h00Label, "cell 1 16 5 1"); add(h00Label, "cell 1 16 5 1");
//---- h0Label ---- //---- h0Label ----
h0Label.setText("H0"); h0Label.setText("H0");
h0Label.putClientProperty("FlatLaf.styleClass", "h0"); h0Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h0");
add(h0Label, "cell 1 16 5 1"); add(h0Label, "cell 1 16 5 1");
//---- h1Label ---- //---- h1Label ----
h1Label.setText("H1"); h1Label.setText("H1");
h1Label.putClientProperty("FlatLaf.styleClass", "h1"); h1Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(h1Label, "cell 1 16 5 1"); add(h1Label, "cell 1 16 5 1");
//---- h2Label ---- //---- h2Label ----
h2Label.setText("H2"); h2Label.setText("H2");
h2Label.putClientProperty("FlatLaf.styleClass", "h2"); h2Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h2");
add(h2Label, "cell 1 16 5 1"); add(h2Label, "cell 1 16 5 1");
//---- h3Label ---- //---- h3Label ----
h3Label.setText("H3"); h3Label.setText("H3");
h3Label.putClientProperty("FlatLaf.styleClass", "h3"); h3Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(h3Label, "cell 1 16 5 1"); add(h3Label, "cell 1 16 5 1");
//---- h4Label ---- //---- h4Label ----
h4Label.setText("H4"); h4Label.setText("H4");
h4Label.putClientProperty("FlatLaf.styleClass", "h4"); h4Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h4");
add(h4Label, "cell 1 16 5 1"); add(h4Label, "cell 1 16 5 1");
//---- lightLabel ---- //---- lightLabel ----
lightLabel.setText("light"); lightLabel.setText("light");
lightLabel.putClientProperty("FlatLaf.style", "font: 200% $light.font"); lightLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $light.font");
add(lightLabel, "cell 1 16 5 1,gapx 30"); add(lightLabel, "cell 1 16 5 1,gapx 30");
//---- semiboldLabel ---- //---- semiboldLabel ----
semiboldLabel.setText("semibold"); semiboldLabel.setText("semibold");
semiboldLabel.putClientProperty("FlatLaf.style", "font: 200% $semibold.font"); semiboldLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $semibold.font");
add(semiboldLabel, "cell 1 16 5 1"); add(semiboldLabel, "cell 1 16 5 1");
//---- fontZoomLabel ---- //---- fontZoomLabel ----
fontZoomLabel.setText("(200%)"); fontZoomLabel.setText("(200%)");
fontZoomLabel.putClientProperty("FlatLaf.styleClass", "small"); fontZoomLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
fontZoomLabel.setEnabled(false); fontZoomLabel.setEnabled(false);
add(fontZoomLabel, "cell 1 16 5 1"); add(fontZoomLabel, "cell 1 16 5 1");
//---- largeLabel ---- //---- largeLabel ----
largeLabel.setText("large"); largeLabel.setText("large");
largeLabel.putClientProperty("FlatLaf.styleClass", "large"); largeLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "large");
add(largeLabel, "cell 1 17 5 1"); add(largeLabel, "cell 1 17 5 1");
//---- defaultLabel ---- //---- defaultLabel ----
@@ -820,22 +820,22 @@ class BasicComponentsPanel
//---- mediumLabel ---- //---- mediumLabel ----
mediumLabel.setText("medium"); mediumLabel.setText("medium");
mediumLabel.putClientProperty("FlatLaf.styleClass", "medium"); mediumLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "medium");
add(mediumLabel, "cell 1 17 5 1"); add(mediumLabel, "cell 1 17 5 1");
//---- smallLabel ---- //---- smallLabel ----
smallLabel.setText("small"); smallLabel.setText("small");
smallLabel.putClientProperty("FlatLaf.styleClass", "small"); smallLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
add(smallLabel, "cell 1 17 5 1"); add(smallLabel, "cell 1 17 5 1");
//---- miniLabel ---- //---- miniLabel ----
miniLabel.setText("mini"); miniLabel.setText("mini");
miniLabel.putClientProperty("FlatLaf.styleClass", "mini"); miniLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "mini");
add(miniLabel, "cell 1 17 5 1"); add(miniLabel, "cell 1 17 5 1");
//---- monospacedLabel ---- //---- monospacedLabel ----
monospacedLabel.setText("monospaced"); monospacedLabel.setText("monospaced");
monospacedLabel.putClientProperty("FlatLaf.styleClass", "monospaced"); monospacedLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "monospaced");
add(monospacedLabel, "cell 1 17 5 1,gapx 30"); add(monospacedLabel, "cell 1 17 5 1,gapx 30");
//======== popupMenu1 ======== //======== popupMenu1 ========

View File

@@ -22,6 +22,7 @@ import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable; import java.awt.datatransfer.Transferable;
import javax.swing.*; import javax.swing.*;
import javax.swing.UIDefaults.ActiveValue;
import javax.swing.table.*; import javax.swing.table.*;
import javax.swing.tree.*; import javax.swing.tree.*;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
@@ -65,6 +66,45 @@ class DataComponentsPanel
tree3.putClientProperty( FlatClientProperties.STYLE, "selectionInsets: 0,1,0,1; selectionArc: 6" ); tree3.putClientProperty( FlatClientProperties.STYLE, "selectionInsets: 0,1,0,1; selectionArc: 6" );
} }
private void listAlternatingRowsChanged() {
ActiveValue alternateRowColor = null;
if( listAlternatingRowsCheckBox.isSelected() ) {
alternateRowColor = table -> {
Color background = list1.getBackground();
return FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
}
UIManager.put( "List.alternateRowColor", alternateRowColor );
list1.updateUI();
list2.updateUI();
list3.updateUI();
}
private void treeWideSelectionChanged() {
boolean wideSelection = treeWideSelectionCheckBox.isSelected();
tree1.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
tree2.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
tree3.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
}
private void treeAlternatingRowsChanged() {
ActiveValue alternateRowColor = null;
if( treeAlternatingRowsCheckBox.isSelected() ) {
alternateRowColor = table -> {
Color background = tree1.getBackground();
return FlatLaf.isLafDark()
? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
}
UIManager.put( "Tree.alternateRowColor", alternateRowColor );
tree1.updateUI();
tree2.updateUI();
tree3.updateUI();
}
private void dndChanged() { private void dndChanged() {
boolean dnd = dndCheckBox.isSelected(); boolean dnd = dndCheckBox.isSelected();
DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION; DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION;
@@ -142,18 +182,20 @@ class DataComponentsPanel
} }
private void alternatingRowsChanged() { private void alternatingRowsChanged() {
Color alternateRowColor = null; ActiveValue alternateRowColor = null;
if( alternatingRowsCheckBox.isSelected() ) { if( alternatingRowsCheckBox.isSelected() ) {
Color background = table1.getBackground(); alternateRowColor = table -> {
alternateRowColor = FlatLaf.isLafDark() Color background = table1.getBackground();
? ColorFunctions.lighten( background, 0.05f ) return FlatLaf.isLafDark()
: ColorFunctions.darken( background, 0.05f ); ? ColorFunctions.lighten( background, 0.05f )
: ColorFunctions.darken( background, 0.05f );
};
} }
UIManager.put( "Table.alternateRowColor", alternateRowColor ); UIManager.put( "Table.alternateRowColor", alternateRowColor );
table1.repaint(); table1.repaint();
} }
@SuppressWarnings( { "unchecked", "rawtypes" } ) @SuppressWarnings( { "rawtypes" } )
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel label1 = new JLabel(); JLabel label1 = new JLabel();
@@ -166,6 +208,8 @@ class DataComponentsPanel
list3 = new JList<>(); list3 = new JList<>();
JScrollPane scrollPane2 = new JScrollPane(); JScrollPane scrollPane2 = new JScrollPane();
list2 = new JList<>(); list2 = new JList<>();
JPanel listOptionsPanel = new JPanel();
listAlternatingRowsCheckBox = new JCheckBox();
JLabel treeLabel = new JLabel(); JLabel treeLabel = new JLabel();
JScrollPane scrollPane3 = new JScrollPane(); JScrollPane scrollPane3 = new JScrollPane();
tree1 = new JTree(); tree1 = new JTree();
@@ -173,6 +217,9 @@ class DataComponentsPanel
tree3 = new JTree(); tree3 = new JTree();
JScrollPane scrollPane4 = new JScrollPane(); JScrollPane scrollPane4 = new JScrollPane();
tree2 = new JTree(); tree2 = new JTree();
JPanel treeOptionsPanel = new JPanel();
treeWideSelectionCheckBox = new JCheckBox();
treeAlternatingRowsCheckBox = new JCheckBox();
JLabel tableLabel = new JLabel(); JLabel tableLabel = new JLabel();
JScrollPane scrollPane5 = new JScrollPane(); JScrollPane scrollPane5 = new JScrollPane();
table1 = new JTable(); table1 = new JTable();
@@ -273,6 +320,22 @@ class DataComponentsPanel
} }
add(scrollPane2, "cell 3 1"); add(scrollPane2, "cell 3 1");
//======== listOptionsPanel ========
{
listOptionsPanel.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]"));
//---- listAlternatingRowsCheckBox ----
listAlternatingRowsCheckBox.setText("alternating rows");
listAlternatingRowsCheckBox.addActionListener(e -> listAlternatingRowsChanged());
listOptionsPanel.add(listAlternatingRowsCheckBox, "cell 0 0");
}
add(listOptionsPanel, "cell 4 1");
//---- treeLabel ---- //---- treeLabel ----
treeLabel.setText("JTree:"); treeLabel.setText("JTree:");
add(treeLabel, "cell 0 2,aligny top,growy 0"); add(treeLabel, "cell 0 2,aligny top,growy 0");
@@ -334,6 +397,29 @@ class DataComponentsPanel
} }
add(scrollPane4, "cell 3 2"); add(scrollPane4, "cell 3 2");
//======== treeOptionsPanel ========
{
treeOptionsPanel.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]0" +
"[]"));
//---- treeWideSelectionCheckBox ----
treeWideSelectionCheckBox.setText("wide selection");
treeWideSelectionCheckBox.setSelected(true);
treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged());
treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 0");
//---- treeAlternatingRowsCheckBox ----
treeAlternatingRowsCheckBox.setText("alternating rows");
treeAlternatingRowsCheckBox.addActionListener(e -> treeAlternatingRowsChanged());
treeOptionsPanel.add(treeAlternatingRowsCheckBox, "cell 0 1");
}
add(treeOptionsPanel, "cell 4 2");
//---- tableLabel ---- //---- tableLabel ----
tableLabel.setText("JTable:"); tableLabel.setText("JTable:");
add(tableLabel, "cell 0 3,aligny top,growy 0"); add(tableLabel, "cell 0 3,aligny top,growy 0");
@@ -379,7 +465,7 @@ class DataComponentsPanel
{ {
TableColumnModel cm = table1.getColumnModel(); TableColumnModel cm = table1.getColumnModel();
cm.getColumn(2).setCellEditor(new DefaultCellEditor( cm.getColumn(2).setCellEditor(new DefaultCellEditor(
new JComboBox(new DefaultComboBoxModel(new String[] { new JComboBox<>(new DefaultComboBoxModel<>(new String[] {
"January", "January",
"February", "February",
"March", "March",
@@ -394,7 +480,7 @@ class DataComponentsPanel
"December" "December"
})))); }))));
cm.getColumn(3).setCellEditor(new DefaultCellEditor( cm.getColumn(3).setCellEditor(new DefaultCellEditor(
new JComboBox(new DefaultComboBoxModel(new String[] { new JComboBox<>(new DefaultComboBoxModel<>(new String[] {
"January", "January",
"February", "February",
"March", "March",
@@ -513,9 +599,12 @@ class DataComponentsPanel
private JList<String> list1; private JList<String> list1;
private JList<String> list3; private JList<String> list3;
private JList<String> list2; private JList<String> list2;
private JCheckBox listAlternatingRowsCheckBox;
private JTree tree1; private JTree tree1;
private JTree tree3; private JTree tree3;
private JTree tree2; private JTree tree2;
private JCheckBox treeWideSelectionCheckBox;
private JCheckBox treeAlternatingRowsCheckBox;
private JTable table1; private JTable table1;
private JCheckBox roundedSelectionCheckBox; private JCheckBox roundedSelectionCheckBox;
private JCheckBox showHorizontalLinesCheckBox; private JCheckBox showHorizontalLinesCheckBox;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8" JFDML JFormDesigner: "8.3" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -92,6 +92,25 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 1" "value": "cell 3 1"
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]"
} ) {
name: "listOptionsPanel"
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "listAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "treeLabel" name: "treeLabel"
"text": "JTree:" "text": "JTree:"
@@ -192,6 +211,36 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 2" "value": "cell 3 2"
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]0[]"
} ) {
name: "treeOptionsPanel"
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeWideSelectionCheckBox"
"text": "wide selection"
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeWideSelectionChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "tableLabel" name: "tableLabel"
"text": "JTable:" "text": "JTable:"

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.demo;
import java.awt.*; import java.awt.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import com.formdev.flatlaf.FlatClientProperties;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -176,12 +177,12 @@ class MoreComponentsPanel
add(scrollBar3, "cell 2 0 1 6,growy"); add(scrollBar3, "cell 2 0 1 6,growy");
//---- scrollBar7 ---- //---- scrollBar7 ----
scrollBar7.putClientProperty("JScrollBar.showButtons", true); scrollBar7.putClientProperty(FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS, true);
add(scrollBar7, "cell 2 0 1 6,growy"); add(scrollBar7, "cell 2 0 1 6,growy");
//---- scrollBar8 ---- //---- scrollBar8 ----
scrollBar8.setEnabled(false); scrollBar8.setEnabled(false);
scrollBar8.putClientProperty("JScrollBar.showButtons", true); scrollBar8.putClientProperty(FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS, true);
add(scrollBar8, "cell 2 0 1 6,growy"); add(scrollBar8, "cell 2 0 1 6,growy");
//---- separator2 ---- //---- separator2 ----
@@ -301,13 +302,13 @@ class MoreComponentsPanel
//---- scrollBar5 ---- //---- scrollBar5 ----
scrollBar5.setOrientation(Adjustable.HORIZONTAL); scrollBar5.setOrientation(Adjustable.HORIZONTAL);
scrollBar5.putClientProperty("JScrollBar.showButtons", true); scrollBar5.putClientProperty(FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS, true);
add(scrollBar5, "cell 1 3,growx"); add(scrollBar5, "cell 1 3,growx");
//---- scrollBar6 ---- //---- scrollBar6 ----
scrollBar6.setOrientation(Adjustable.HORIZONTAL); scrollBar6.setOrientation(Adjustable.HORIZONTAL);
scrollBar6.setEnabled(false); scrollBar6.setEnabled(false);
scrollBar6.putClientProperty("JScrollBar.showButtons", true); scrollBar6.putClientProperty(FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS, true);
add(scrollBar6, "cell 1 4,growx"); add(scrollBar6, "cell 1 4,growx");
//---- separatorLabel ---- //---- separatorLabel ----
@@ -518,7 +519,7 @@ class MoreComponentsPanel
//======== panel5 ======== //======== panel5 ========
{ {
panel5.putClientProperty("FlatLaf.style", "arc: 16; background: darken($Panel.background,5%)"); panel5.putClientProperty(FlatClientProperties.STYLE, "arc: 16; background: darken($Panel.background,5%)");
panel5.setLayout(new BorderLayout()); panel5.setLayout(new BorderLayout());
//---- label9 ---- //---- label9 ----
@@ -530,7 +531,7 @@ class MoreComponentsPanel
//======== panel4 ======== //======== panel4 ========
{ {
panel4.putClientProperty("FlatLaf.style", "border: 1,1,1,1,@disabledForeground,1,16; background: darken($Panel.background,5%)"); panel4.putClientProperty(FlatClientProperties.STYLE, "border: 1,1,1,1,@disabledForeground,1,16; background: darken($Panel.background,5%)");
panel4.setLayout(new BorderLayout()); panel4.setLayout(new BorderLayout());
//---- label8 ---- //---- label8 ----
@@ -546,14 +547,14 @@ class MoreComponentsPanel
//---- label13 ---- //---- label13 ----
label13.setText("rounded background"); label13.setText("rounded background");
label13.putClientProperty("FlatLaf.style", "arc: 999; border: 2,10,2,10"); label13.putClientProperty(FlatClientProperties.STYLE, "arc: 999; border: 2,10,2,10");
label13.setBackground(new Color(0xb8e4f3)); label13.setBackground(new Color(0xb8e4f3));
label13.setForeground(new Color(0x135b76)); label13.setForeground(new Color(0x135b76));
add(label13, "cell 1 13 4 1"); add(label13, "cell 1 13 4 1");
//---- label10 ---- //---- label10 ----
label10.setText("rounded border"); label10.setText("rounded border");
label10.putClientProperty("FlatLaf.style", "arc: 999; border: 2,10,2,10,#135b76"); label10.putClientProperty(FlatClientProperties.STYLE, "arc: 999; border: 2,10,2,10,#135b76");
label10.setBackground(new Color(0xb8e4f3)); label10.setBackground(new Color(0xb8e4f3));
label10.setForeground(new Color(0x135b76)); label10.setForeground(new Color(0x135b76));
add(label10, "cell 1 13 4 1"); add(label10, "cell 1 13 4 1");

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.demo; package com.formdev.flatlaf.demo;
import com.formdev.flatlaf.FlatClientProperties;
import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
@@ -471,7 +472,7 @@ class TabsPanel
//---- tabPlacementLabel ---- //---- tabPlacementLabel ----
tabPlacementLabel.setText("Tab placement"); tabPlacementLabel.setText("Tab placement");
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabPlacementLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel1.add(tabPlacementLabel, "cell 0 0"); panel1.add(tabPlacementLabel, "cell 0 0");
//======== tabPlacementToolBar ======== //======== tabPlacementToolBar ========
@@ -482,38 +483,38 @@ class TabsPanel
//---- topPlacementButton ---- //---- topPlacementButton ----
topPlacementButton.setText("top"); topPlacementButton.setText("top");
topPlacementButton.setSelected(true); topPlacementButton.setSelected(true);
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small"); topPlacementButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
topPlacementButton.addActionListener(e -> tabPlacementChanged()); topPlacementButton.addActionListener(e -> tabPlacementChanged());
tabPlacementToolBar.add(topPlacementButton); tabPlacementToolBar.add(topPlacementButton);
//---- bottomPlacementButton ---- //---- bottomPlacementButton ----
bottomPlacementButton.setText("bottom"); bottomPlacementButton.setText("bottom");
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small"); bottomPlacementButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
bottomPlacementButton.addActionListener(e -> tabPlacementChanged()); bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
tabPlacementToolBar.add(bottomPlacementButton); tabPlacementToolBar.add(bottomPlacementButton);
//---- leftPlacementButton ---- //---- leftPlacementButton ----
leftPlacementButton.setText("left"); leftPlacementButton.setText("left");
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small"); leftPlacementButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
leftPlacementButton.addActionListener(e -> tabPlacementChanged()); leftPlacementButton.addActionListener(e -> tabPlacementChanged());
tabPlacementToolBar.add(leftPlacementButton); tabPlacementToolBar.add(leftPlacementButton);
//---- rightPlacementButton ---- //---- rightPlacementButton ----
rightPlacementButton.setText("right"); rightPlacementButton.setText("right");
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small"); rightPlacementButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
rightPlacementButton.addActionListener(e -> tabPlacementChanged()); rightPlacementButton.addActionListener(e -> tabPlacementChanged());
tabPlacementToolBar.add(rightPlacementButton); tabPlacementToolBar.add(rightPlacementButton);
tabPlacementToolBar.addSeparator(); tabPlacementToolBar.addSeparator();
//---- scrollButton ---- //---- scrollButton ----
scrollButton.setText("scroll"); scrollButton.setText("scroll");
scrollButton.putClientProperty("FlatLaf.styleClass", "small"); scrollButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollButton.addActionListener(e -> scrollChanged()); scrollButton.addActionListener(e -> scrollChanged());
tabPlacementToolBar.add(scrollButton); tabPlacementToolBar.add(scrollButton);
//---- borderButton ---- //---- borderButton ----
borderButton.setText("border"); borderButton.setText("border");
borderButton.putClientProperty("FlatLaf.styleClass", "small"); borderButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
borderButton.addActionListener(e -> borderChanged()); borderButton.addActionListener(e -> borderChanged());
tabPlacementToolBar.add(borderButton); tabPlacementToolBar.add(borderButton);
} }
@@ -522,7 +523,7 @@ class TabsPanel
//---- tabLayoutLabel ---- //---- tabLayoutLabel ----
tabLayoutLabel.setText("Tab layout"); tabLayoutLabel.setText("Tab layout");
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabLayoutLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel1.add(tabLayoutLabel, "cell 0 2"); panel1.add(tabLayoutLabel, "cell 0 2");
//======== tabLayoutToolBar ======== //======== tabLayoutToolBar ========
@@ -533,13 +534,13 @@ class TabsPanel
//---- scrollTabLayoutButton ---- //---- scrollTabLayoutButton ----
scrollTabLayoutButton.setText("scroll"); scrollTabLayoutButton.setText("scroll");
scrollTabLayoutButton.setSelected(true); scrollTabLayoutButton.setSelected(true);
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small"); scrollTabLayoutButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged()); scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
tabLayoutToolBar.add(scrollTabLayoutButton); tabLayoutToolBar.add(scrollTabLayoutButton);
//---- wrapTabLayoutButton ---- //---- wrapTabLayoutButton ----
wrapTabLayoutButton.setText("wrap"); wrapTabLayoutButton.setText("wrap");
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small"); wrapTabLayoutButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged()); wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
tabLayoutToolBar.add(wrapTabLayoutButton); tabLayoutToolBar.add(wrapTabLayoutButton);
} }
@@ -548,20 +549,20 @@ class TabsPanel
//---- scrollLayoutNoteLabel ---- //---- scrollLayoutNoteLabel ----
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)"); scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
scrollLayoutNoteLabel.setEnabled(false); scrollLayoutNoteLabel.setEnabled(false);
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small"); scrollLayoutNoteLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel1.add(scrollLayoutNoteLabel, "cell 0 3"); panel1.add(scrollLayoutNoteLabel, "cell 0 3");
//---- wrapLayoutNoteLabel ---- //---- wrapLayoutNoteLabel ----
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)"); wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
wrapLayoutNoteLabel.setEnabled(false); wrapLayoutNoteLabel.setEnabled(false);
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small"); wrapLayoutNoteLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel1.add(wrapLayoutNoteLabel, "cell 0 3"); panel1.add(wrapLayoutNoteLabel, "cell 0 3");
panel1.add(scrollLayoutTabbedPane, "cell 0 4"); panel1.add(scrollLayoutTabbedPane, "cell 0 4");
panel1.add(wrapLayoutTabbedPane, "cell 0 4,width 100:100,height pref*2px"); panel1.add(wrapLayoutTabbedPane, "cell 0 4,width 100:100,height pref*2px");
//---- closableTabsLabel ---- //---- closableTabsLabel ----
closableTabsLabel.setText("Closable tabs"); closableTabsLabel.setText("Closable tabs");
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3"); closableTabsLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel1.add(closableTabsLabel, "cell 0 5"); panel1.add(closableTabsLabel, "cell 0 5");
//======== closableTabsToolBar ======== //======== closableTabsToolBar ========
@@ -572,19 +573,19 @@ class TabsPanel
//---- squareCloseButton ---- //---- squareCloseButton ----
squareCloseButton.setText("square"); squareCloseButton.setText("square");
squareCloseButton.setSelected(true); squareCloseButton.setSelected(true);
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small"); squareCloseButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
squareCloseButton.addActionListener(e -> closeButtonStyleChanged()); squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
closableTabsToolBar.add(squareCloseButton); closableTabsToolBar.add(squareCloseButton);
//---- circleCloseButton ---- //---- circleCloseButton ----
circleCloseButton.setText("circle"); circleCloseButton.setText("circle");
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small"); circleCloseButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
circleCloseButton.addActionListener(e -> closeButtonStyleChanged()); circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
closableTabsToolBar.add(circleCloseButton); closableTabsToolBar.add(circleCloseButton);
//---- redCrossCloseButton ---- //---- redCrossCloseButton ----
redCrossCloseButton.setText("red cross"); redCrossCloseButton.setText("red cross");
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small"); redCrossCloseButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged()); redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
closableTabsToolBar.add(redCrossCloseButton); closableTabsToolBar.add(redCrossCloseButton);
} }
@@ -593,7 +594,7 @@ class TabsPanel
//---- tabAreaComponentsLabel ---- //---- tabAreaComponentsLabel ----
tabAreaComponentsLabel.setText("Custom tab area components"); tabAreaComponentsLabel.setText("Custom tab area components");
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabAreaComponentsLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel1.add(tabAreaComponentsLabel, "cell 0 7"); panel1.add(tabAreaComponentsLabel, "cell 0 7");
//======== tabAreaComponentsToolBar ======== //======== tabAreaComponentsToolBar ========
@@ -604,14 +605,14 @@ class TabsPanel
//---- leadingComponentButton ---- //---- leadingComponentButton ----
leadingComponentButton.setText("leading"); leadingComponentButton.setText("leading");
leadingComponentButton.setSelected(true); leadingComponentButton.setSelected(true);
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small"); leadingComponentButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
leadingComponentButton.addActionListener(e -> customComponentsChanged()); leadingComponentButton.addActionListener(e -> customComponentsChanged());
tabAreaComponentsToolBar.add(leadingComponentButton); tabAreaComponentsToolBar.add(leadingComponentButton);
//---- trailingComponentButton ---- //---- trailingComponentButton ----
trailingComponentButton.setText("trailing"); trailingComponentButton.setText("trailing");
trailingComponentButton.setSelected(true); trailingComponentButton.setSelected(true);
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small"); trailingComponentButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
trailingComponentButton.addActionListener(e -> customComponentsChanged()); trailingComponentButton.addActionListener(e -> customComponentsChanged());
tabAreaComponentsToolBar.add(trailingComponentButton); tabAreaComponentsToolBar.add(trailingComponentButton);
} }
@@ -642,13 +643,13 @@ class TabsPanel
//---- tabIconPlacementLabel ---- //---- tabIconPlacementLabel ----
tabIconPlacementLabel.setText("Tab icon placement"); tabIconPlacementLabel.setText("Tab icon placement");
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabIconPlacementLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel2.add(tabIconPlacementLabel, "cell 0 0"); panel2.add(tabIconPlacementLabel, "cell 0 0");
//---- tabIconPlacementNodeLabel ---- //---- tabIconPlacementNodeLabel ----
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)"); tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
tabIconPlacementNodeLabel.setEnabled(false); tabIconPlacementNodeLabel.setEnabled(false);
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small"); tabIconPlacementNodeLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel2.add(tabIconPlacementNodeLabel, "cell 0 1"); panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
panel2.add(iconTopTabbedPane, "cell 0 2"); panel2.add(iconTopTabbedPane, "cell 0 2");
panel2.add(iconBottomTabbedPane, "cell 0 3"); panel2.add(iconBottomTabbedPane, "cell 0 3");
@@ -657,13 +658,13 @@ class TabsPanel
//---- tabAreaAlignmentLabel ---- //---- tabAreaAlignmentLabel ----
tabAreaAlignmentLabel.setText("Tab area alignment"); tabAreaAlignmentLabel.setText("Tab area alignment");
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabAreaAlignmentLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel2.add(tabAreaAlignmentLabel, "cell 0 6"); panel2.add(tabAreaAlignmentLabel, "cell 0 6");
//---- tabAreaAlignmentNoteLabel ---- //---- tabAreaAlignmentNoteLabel ----
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)"); tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
tabAreaAlignmentNoteLabel.setEnabled(false); tabAreaAlignmentNoteLabel.setEnabled(false);
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small"); tabAreaAlignmentNoteLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7"); panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
panel2.add(alignLeadingTabbedPane, "cell 0 8"); panel2.add(alignLeadingTabbedPane, "cell 0 8");
panel2.add(alignCenterTabbedPane, "cell 0 9"); panel2.add(alignCenterTabbedPane, "cell 0 9");
@@ -692,13 +693,13 @@ class TabsPanel
//---- tabWidthModeLabel ---- //---- tabWidthModeLabel ----
tabWidthModeLabel.setText("Tab width mode"); tabWidthModeLabel.setText("Tab width mode");
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabWidthModeLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel3.add(tabWidthModeLabel, "cell 0 0"); panel3.add(tabWidthModeLabel, "cell 0 0");
//---- tabWidthModeNoteLabel ---- //---- tabWidthModeNoteLabel ----
tabWidthModeNoteLabel.setText("(preferred/equal/compact)"); tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
tabWidthModeNoteLabel.setEnabled(false); tabWidthModeNoteLabel.setEnabled(false);
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small"); tabWidthModeNoteLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel3.add(tabWidthModeNoteLabel, "cell 0 1"); panel3.add(tabWidthModeNoteLabel, "cell 0 1");
panel3.add(widthPreferredTabbedPane, "cell 0 2"); panel3.add(widthPreferredTabbedPane, "cell 0 2");
panel3.add(widthEqualTabbedPane, "cell 0 3"); panel3.add(widthEqualTabbedPane, "cell 0 3");
@@ -706,14 +707,14 @@ class TabsPanel
//---- minMaxTabWidthLabel ---- //---- minMaxTabWidthLabel ----
minMaxTabWidthLabel.setText("Minimum/maximum tab width"); minMaxTabWidthLabel.setText("Minimum/maximum tab width");
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3"); minMaxTabWidthLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel3.add(minMaxTabWidthLabel, "cell 0 5"); panel3.add(minMaxTabWidthLabel, "cell 0 5");
panel3.add(minimumTabWidthTabbedPane, "cell 0 6"); panel3.add(minimumTabWidthTabbedPane, "cell 0 6");
panel3.add(maximumTabWidthTabbedPane, "cell 0 7"); panel3.add(maximumTabWidthTabbedPane, "cell 0 7");
//---- tabAlignmentLabel ---- //---- tabAlignmentLabel ----
tabAlignmentLabel.setText("Tab title alignment"); tabAlignmentLabel.setText("Tab title alignment");
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3"); tabAlignmentLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
panel3.add(tabAlignmentLabel, "cell 0 8"); panel3.add(tabAlignmentLabel, "cell 0 8");
//======== panel5 ======== //======== panel5 ========
@@ -733,13 +734,13 @@ class TabsPanel
//---- tabAlignmentNoteLabel ---- //---- tabAlignmentNoteLabel ----
tabAlignmentNoteLabel.setText("(leading/center/trailing)"); tabAlignmentNoteLabel.setText("(leading/center/trailing)");
tabAlignmentNoteLabel.setEnabled(false); tabAlignmentNoteLabel.setEnabled(false);
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small"); tabAlignmentNoteLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel5.add(tabAlignmentNoteLabel, "cell 0 0"); panel5.add(tabAlignmentNoteLabel, "cell 0 0");
//---- tabAlignmentNoteLabel2 ---- //---- tabAlignmentNoteLabel2 ----
tabAlignmentNoteLabel2.setText("(trailing)"); tabAlignmentNoteLabel2.setText("(trailing)");
tabAlignmentNoteLabel2.setEnabled(false); tabAlignmentNoteLabel2.setEnabled(false);
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small"); tabAlignmentNoteLabel2.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0"); panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
panel5.add(tabAlignLeadingTabbedPane, "cell 0 1"); panel5.add(tabAlignLeadingTabbedPane, "cell 0 1");
@@ -787,19 +788,19 @@ class TabsPanel
//---- scrollAsNeededSingleButton ---- //---- scrollAsNeededSingleButton ----
scrollAsNeededSingleButton.setText("asNeededSingle"); scrollAsNeededSingleButton.setText("asNeededSingle");
scrollAsNeededSingleButton.setSelected(true); scrollAsNeededSingleButton.setSelected(true);
scrollAsNeededSingleButton.putClientProperty("FlatLaf.styleClass", "small"); scrollAsNeededSingleButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollAsNeededSingleButton.addActionListener(e -> scrollButtonsPolicyChanged()); scrollAsNeededSingleButton.addActionListener(e -> scrollButtonsPolicyChanged());
scrollButtonsPolicyToolBar.add(scrollAsNeededSingleButton); scrollButtonsPolicyToolBar.add(scrollAsNeededSingleButton);
//---- scrollAsNeededButton ---- //---- scrollAsNeededButton ----
scrollAsNeededButton.setText("asNeeded"); scrollAsNeededButton.setText("asNeeded");
scrollAsNeededButton.putClientProperty("FlatLaf.styleClass", "small"); scrollAsNeededButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollAsNeededButton.addActionListener(e -> scrollButtonsPolicyChanged()); scrollAsNeededButton.addActionListener(e -> scrollButtonsPolicyChanged());
scrollButtonsPolicyToolBar.add(scrollAsNeededButton); scrollButtonsPolicyToolBar.add(scrollAsNeededButton);
//---- scrollNeverButton ---- //---- scrollNeverButton ----
scrollNeverButton.setText("never"); scrollNeverButton.setText("never");
scrollNeverButton.putClientProperty("FlatLaf.styleClass", "small"); scrollNeverButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollNeverButton.addActionListener(e -> scrollButtonsPolicyChanged()); scrollNeverButton.addActionListener(e -> scrollButtonsPolicyChanged());
scrollButtonsPolicyToolBar.add(scrollNeverButton); scrollButtonsPolicyToolBar.add(scrollNeverButton);
} }
@@ -817,13 +818,13 @@ class TabsPanel
//---- popupAsNeededButton ---- //---- popupAsNeededButton ----
popupAsNeededButton.setText("asNeeded"); popupAsNeededButton.setText("asNeeded");
popupAsNeededButton.setSelected(true); popupAsNeededButton.setSelected(true);
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small"); popupAsNeededButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged()); popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
tabsPopupPolicyToolBar.add(popupAsNeededButton); tabsPopupPolicyToolBar.add(popupAsNeededButton);
//---- popupNeverButton ---- //---- popupNeverButton ----
popupNeverButton.setText("never"); popupNeverButton.setText("never");
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small"); popupNeverButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged()); popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
tabsPopupPolicyToolBar.add(popupNeverButton); tabsPopupPolicyToolBar.add(popupNeverButton);
} }
@@ -846,13 +847,13 @@ class TabsPanel
//---- scrollBothButton ---- //---- scrollBothButton ----
scrollBothButton.setText("both"); scrollBothButton.setText("both");
scrollBothButton.setSelected(true); scrollBothButton.setSelected(true);
scrollBothButton.putClientProperty("FlatLaf.styleClass", "small"); scrollBothButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollBothButton.addActionListener(e -> scrollButtonsPlacementChanged()); scrollBothButton.addActionListener(e -> scrollButtonsPlacementChanged());
scrollButtonsPlacementToolBar.add(scrollBothButton); scrollButtonsPlacementToolBar.add(scrollBothButton);
//---- scrollTrailingButton ---- //---- scrollTrailingButton ----
scrollTrailingButton.setText("trailing"); scrollTrailingButton.setText("trailing");
scrollTrailingButton.putClientProperty("FlatLaf.styleClass", "small"); scrollTrailingButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged()); scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
scrollButtonsPlacementToolBar.add(scrollTrailingButton); scrollButtonsPlacementToolBar.add(scrollTrailingButton);
} }
@@ -869,13 +870,13 @@ class TabsPanel
//---- underlinedTabTypeButton ---- //---- underlinedTabTypeButton ----
underlinedTabTypeButton.setText("underlined"); underlinedTabTypeButton.setText("underlined");
underlinedTabTypeButton.setSelected(true); underlinedTabTypeButton.setSelected(true);
underlinedTabTypeButton.putClientProperty("FlatLaf.styleClass", "small"); underlinedTabTypeButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
underlinedTabTypeButton.addActionListener(e -> tabTypeChanged()); underlinedTabTypeButton.addActionListener(e -> tabTypeChanged());
tabTypeToolBar.add(underlinedTabTypeButton); tabTypeToolBar.add(underlinedTabTypeButton);
//---- cardTabTypeButton ---- //---- cardTabTypeButton ----
cardTabTypeButton.setText("card"); cardTabTypeButton.setText("card");
cardTabTypeButton.putClientProperty("FlatLaf.styleClass", "small"); cardTabTypeButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
cardTabTypeButton.addActionListener(e -> tabTypeChanged()); cardTabTypeButton.addActionListener(e -> tabTypeChanged());
tabTypeToolBar.add(cardTabTypeButton); tabTypeToolBar.add(cardTabTypeButton);
} }
@@ -893,25 +894,25 @@ class TabsPanel
//---- rotationNoneButton ---- //---- rotationNoneButton ----
rotationNoneButton.setText("none"); rotationNoneButton.setText("none");
rotationNoneButton.setSelected(true); rotationNoneButton.setSelected(true);
rotationNoneButton.putClientProperty("FlatLaf.styleClass", "small"); rotationNoneButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
rotationNoneButton.addActionListener(e -> tabRotationChanged()); rotationNoneButton.addActionListener(e -> tabRotationChanged());
tabRotationToolBar.add(rotationNoneButton); tabRotationToolBar.add(rotationNoneButton);
//---- rotationAutoButton ---- //---- rotationAutoButton ----
rotationAutoButton.setText("auto"); rotationAutoButton.setText("auto");
rotationAutoButton.putClientProperty("FlatLaf.styleClass", "small"); rotationAutoButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
rotationAutoButton.addActionListener(e -> tabRotationChanged()); rotationAutoButton.addActionListener(e -> tabRotationChanged());
tabRotationToolBar.add(rotationAutoButton); tabRotationToolBar.add(rotationAutoButton);
//---- rotationLeftButton ---- //---- rotationLeftButton ----
rotationLeftButton.setText("left"); rotationLeftButton.setText("left");
rotationLeftButton.putClientProperty("FlatLaf.styleClass", "small"); rotationLeftButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
rotationLeftButton.addActionListener(e -> tabRotationChanged()); rotationLeftButton.addActionListener(e -> tabRotationChanged());
tabRotationToolBar.add(rotationLeftButton); tabRotationToolBar.add(rotationLeftButton);
//---- rotationRightButton ---- //---- rotationRightButton ----
rotationRightButton.setText("right"); rotationRightButton.setText("right");
rotationRightButton.putClientProperty("FlatLaf.styleClass", "small"); rotationRightButton.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
rotationRightButton.addActionListener(e -> tabRotationChanged()); rotationRightButton.addActionListener(e -> tabRotationChanged());
tabRotationToolBar.add(rotationRightButton); tabRotationToolBar.add(rotationRightButton);
} }

View File

@@ -45,6 +45,7 @@ import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.border.CompoundBorder; import javax.swing.border.CompoundBorder;
import javax.swing.event.*; import javax.swing.event.*;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf; import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf; import com.formdev.flatlaf.FlatIntelliJLaf;
@@ -554,7 +555,7 @@ public class IJThemesPanel
"light", "light",
"dark" "dark"
})); }));
filterComboBox.putClientProperty("JComponent.minimumWidth", 0); filterComboBox.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
filterComboBox.setFocusable(false); filterComboBox.setFocusable(false);
filterComboBox.addActionListener(e -> filterChanged()); filterComboBox.addActionListener(e -> filterChanged());
add(filterComboBox, "cell 0 0,alignx right,growx 0"); add(filterComboBox, "cell 0 0,alignx right,growx 0");

View File

@@ -24,6 +24,7 @@ import java.awt.Dimension;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Insets; import java.awt.Insets;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.LayoutManager; import java.awt.LayoutManager;
@@ -124,9 +125,12 @@ public class FlatInspector
* Installs a key listener into the application that allows enabling and disabling * Installs a key listener into the application that allows enabling and disabling
* the UI inspector with the given keystroke (e.g. "ctrl shift alt X"). * the UI inspector with the given keystroke (e.g. "ctrl shift alt X").
* *
* @param activationKeys a keystroke (e.g. "ctrl shift alt X") * @param activationKeys a keystroke (e.g. "ctrl shift alt X"), or {@code null} to use "ctrl shift alt X"
*/ */
public static void install( String activationKeys ) { public static void install( String activationKeys ) {
if( activationKeys == null )
activationKeys = "ctrl shift alt X";
KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys ); KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys );
Toolkit.getDefaultToolkit().addAWTEventListener( e -> { Toolkit.getDefaultToolkit().addAWTEventListener( e -> {
if( e.getID() == KeyEvent.KEY_RELEASED && if( e.getID() == KeyEvent.KEY_RELEASED &&
@@ -450,15 +454,18 @@ public class FlatInspector
Dimension size = tip.getPreferredSize(); Dimension size = tip.getPreferredSize();
// position the tip in the visible area // position the tip in the visible area
Rectangle visibleRect = rootPane.getGraphicsConfiguration().getBounds(); GraphicsConfiguration gc = rootPane.getGraphicsConfiguration();
if( tx + size.width > visibleRect.x + visibleRect.width ) if( gc != null ) {
tx -= size.width + UIScale.scale( 16 ); Rectangle visibleRect = gc.getBounds();
if( ty + size.height > visibleRect.y + visibleRect.height ) if( tx + size.width > visibleRect.x + visibleRect.width )
ty -= size.height + UIScale.scale( 32 ); tx -= size.width + UIScale.scale( 16 );
if( tx < visibleRect.x ) if( ty + size.height > visibleRect.y + visibleRect.height )
tx = visibleRect.x; ty -= size.height + UIScale.scale( 32 );
if( ty < visibleRect.y ) if( tx < visibleRect.x )
ty = visibleRect.y; tx = visibleRect.x;
if( ty < visibleRect.y )
ty = visibleRect.y;
}
PopupFactory popupFactory = PopupFactory.getSharedInstance(); PopupFactory popupFactory = PopupFactory.getSharedInstance();
popup = popupFactory.getPopup( c, tip, tx, ty ); popup = popupFactory.getPopup( c, tip, tx, ty );

View File

@@ -37,6 +37,7 @@ import java.net.URL;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@@ -588,7 +589,12 @@ public class FlatSVGIcon
: GrayFilter.createDisabledIconFilter( dark ); : GrayFilter.createDisabledIconFilter( dark );
} }
Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), colorFilter, ColorFilter.getInstance(), grayFilter ); ColorFilter globalColorFilter = ColorFilter.getInstance();
globalColorFilter.c = c;
if( colorFilter != null )
colorFilter.c = c;
Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), colorFilter, globalColorFilter, grayFilter );
try { try {
setRenderingHints( g2 ); setRenderingHints( g2 );
@@ -596,6 +602,10 @@ public class FlatSVGIcon
paintSvg( g2, x, y ); paintSvg( g2, x, y );
} finally { } finally {
g2.dispose(); g2.dispose();
globalColorFilter.c = null;
if( colorFilter != null )
colorFilter.c = null;
} }
} }
@@ -760,6 +770,8 @@ public class FlatSVGIcon
private Map<Color, Color> colorMap; private Map<Color, Color> colorMap;
private Map<Color, Color> darkColorMap; private Map<Color, Color> darkColorMap;
private Function<Color, Color> mapper; private Function<Color, Color> mapper;
private BiFunction<Component, Color, Color> mapperEx;
private Component c;
/** /**
* Returns the global ColorFilter that is applied to all icons. * Returns the global ColorFilter that is applied to all icons.
@@ -800,6 +812,22 @@ public class FlatSVGIcon
setMapper( mapper ); setMapper( mapper );
} }
/**
* Creates a color modifying function that changes painted colors.
* The {@link BiFunction} gets passed the component and
* the original color and returns a modified one.
* <p>
* Examples:
* A ColorFilter can be used to brighten colors of the icon (depending on component state if desired):
* <pre>new ColorFilter( (c, color) -&gt; c.isEnabled() ? color.brighter() : color );</pre>
*
* @param mapperEx The color mapper function
* @since 3.6
*/
public ColorFilter( BiFunction<Component, Color, Color> mapperEx ) {
setMapperEx( mapperEx );
}
/** /**
* Returns a color modifying function or {@code null} * Returns a color modifying function or {@code null}
* *
@@ -821,12 +849,39 @@ public class FlatSVGIcon
* <pre>filter.setMapper( color -&gt; Color.RED );</pre> * <pre>filter.setMapper( color -&gt; Color.RED );</pre>
* *
* @param mapper The color mapper function * @param mapper The color mapper function
* @see #setMapperEx(BiFunction)
* @since 1.2 * @since 1.2
*/ */
public void setMapper( Function<Color, Color> mapper ) { public void setMapper( Function<Color, Color> mapper ) {
this.mapper = mapper; this.mapper = mapper;
} }
/**
* Returns a color modifying function or {@code null}
*
* @since 3.6
*/
public BiFunction<Component, Color, Color> getMapperEx() {
return mapperEx;
}
/**
* Sets a color modifying function that changes painted colors.
* The {@link BiFunction} gets passed the component and
* the original color and returns a modified one.
* <p>
* Examples:
* A ColorFilter can be used to brighten colors of the icon (depending on component state if desired):
* <pre>filter.setMapperEx( (c, color) -&gt; c.isEnabled() ? color.brighter() : color );</pre>
*
* @param mapperEx The color mapper function
* @see #setMapper(Function)
* @since 3.6
*/
public void setMapperEx( BiFunction<Component, Color, Color> mapperEx ) {
this.mapperEx = mapperEx;
}
/** /**
* Returns the color mappings used for light themes. * Returns the color mappings used for light themes.
* *
@@ -936,6 +991,11 @@ public class FlatSVGIcon
} }
public Color filter( Color color ) { public Color filter( Color color ) {
return filter( c, color );
}
/** @since 3.6 */
public Color filter( Component c, Color color ) {
// apply mappings // apply mappings
color = applyMappings( color ); color = applyMappings( color );
@@ -943,6 +1003,10 @@ public class FlatSVGIcon
if( mapper != null ) if( mapper != null )
color = mapper.apply( color ); color = mapper.apply( color );
// apply mapperEx function
if( mapperEx != null )
color = mapperEx.apply( c, color );
return color; return color;
} }
@@ -974,6 +1038,16 @@ public class FlatSVGIcon
return color; return color;
} }
/**
* Returns the component passed to {@link FlatSVGIcon#paintIcon(Component, Graphics, int, int)}.
* This allows color mapping depend on component state (e.g. enabled, selected, hover, etc).
*
* @since 3.6
*/
public Component getPaintingComponent() {
return c;
}
/** /**
* Creates a color modifying function that uses {@link RGBImageFilter#filterRGB(int, int, int)}. * Creates a color modifying function that uses {@link RGBImageFilter#filterRGB(int, int, int)}.
* Can be set to a {@link ColorFilter} using {@link ColorFilter#setMapper(Function)}. * Can be set to a {@link ColorFilter} using {@link ColorFilter#setMapper(Function)}.

View File

@@ -85,9 +85,12 @@ public class FlatUIDefaultsInspector
* Installs a key listener into the application that allows enabling and disabling * Installs a key listener into the application that allows enabling and disabling
* the UI inspector with the given keystroke (e.g. "ctrl shift alt Y"). * the UI inspector with the given keystroke (e.g. "ctrl shift alt Y").
* *
* @param activationKeys a keystroke (e.g. "ctrl shift alt Y") * @param activationKeys a keystroke (e.g. "ctrl shift alt Y"), or {@code null} to use "ctrl shift alt Y"
*/ */
public static void install( String activationKeys ) { public static void install( String activationKeys ) {
if( activationKeys == null )
activationKeys = "ctrl shift alt Y";
KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys ); KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys );
Toolkit.getDefaultToolkit().addAWTEventListener( e -> { Toolkit.getDefaultToolkit().addAWTEventListener( e -> {
if( e.getID() == KeyEvent.KEY_RELEASED && if( e.getID() == KeyEvent.KEY_RELEASED &&

View File

@@ -29,19 +29,37 @@ public class FlatTree
implements FlatComponentExtension, FlatStyleableComponent implements FlatComponentExtension, FlatStyleableComponent
{ {
/** /**
* Returns if the tree shows a wide selection * Returns whether tree shows a wide selection
*/ */
public boolean isWideSelection() { public boolean isWideSelection() {
return getClientPropertyBoolean( TREE_WIDE_SELECTION, "Tree.wideSelection" ); return getClientPropertyBoolean( TREE_WIDE_SELECTION, "Tree.wideSelection" );
} }
/** /**
* Sets if the tree shows a wide selection * Specifies whether tree shows a wide selection
*/ */
public void setWideSelection( boolean wideSelection ) { public void setWideSelection( boolean wideSelection ) {
putClientProperty( TREE_WIDE_SELECTION, wideSelection ); putClientProperty( TREE_WIDE_SELECTION, wideSelection );
} }
/**
* Returns whether tree uses a wide cell renderer.
*
* @since 3.6
*/
public boolean isWideCellRenderer() {
return getClientPropertyBoolean( TREE_WIDE_CELL_RENDERER, "Tree.wideCellRenderer" );
}
/**
* Specifies whether tree uses a wide cell renderer.
*
* @since 3.6
*/
public void setWideCellRenderer( boolean wideCellRenderer ) {
putClientProperty( TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}
/** /**
* Returns whether tree item selection is painted. Default is {@code true}. * Returns whether tree item selection is painted. Default is {@code true}.
* If set to {@code false}, then the tree cell renderer is responsible for painting selection. * If set to {@code false}, then the tree cell renderer is responsible for painting selection.

View File

@@ -62,6 +62,9 @@ CheckBox.icon.pressedBackground = CheckBox.icon.background
CheckBox.icon.focusedSelectedBackground = CheckBox.icon.selectedBackground CheckBox.icon.focusedSelectedBackground = CheckBox.icon.selectedBackground
CheckBox.icon.hoverSelectedBackground = CheckBox.icon.selectedBackground CheckBox.icon.hoverSelectedBackground = CheckBox.icon.selectedBackground
CheckBox.icon.pressedSelectedBackground = CheckBox.icon.selectedBackground CheckBox.icon.pressedSelectedBackground = CheckBox.icon.selectedBackground
CheckBox.icon.focusedIndeterminateBackground = CheckBox.icon.indeterminateBackground
CheckBox.icon.hoverIndeterminateBackground = CheckBox.icon.indeterminateBackground
CheckBox.icon.pressedIndeterminateBackground = CheckBox.icon.indeterminateBackground
CheckBox.icon[filled].disabledBackground = CheckBox.icon[filled].background CheckBox.icon[filled].disabledBackground = CheckBox.icon[filled].background
CheckBox.icon[filled].focusedBackground = CheckBox.icon[filled].background CheckBox.icon[filled].focusedBackground = CheckBox.icon[filled].background
@@ -70,7 +73,9 @@ CheckBox.icon[filled].pressedBackground = CheckBox.icon[filled].background
CheckBox.icon[filled].focusedSelectedBackground = CheckBox.icon[filled].selectedBackground CheckBox.icon[filled].focusedSelectedBackground = CheckBox.icon[filled].selectedBackground
CheckBox.icon[filled].hoverSelectedBackground = CheckBox.icon[filled].selectedBackground CheckBox.icon[filled].hoverSelectedBackground = CheckBox.icon[filled].selectedBackground
CheckBox.icon[filled].pressedSelectedBackground = CheckBox.icon[filled].selectedBackground CheckBox.icon[filled].pressedSelectedBackground = CheckBox.icon[filled].selectedBackground
CheckBox.icon[filled].focusedIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground
CheckBox.icon[filled].hoverIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground
CheckBox.icon[filled].pressedIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground
#---- CheckBoxMenuItem ---- #---- CheckBoxMenuItem ----

View File

@@ -23,6 +23,7 @@ import javax.swing.LookAndFeel;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UIDefaults.ActiveValue; import javax.swing.UIDefaults.ActiveValue;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDefaultsAddon; import com.formdev.flatlaf.FlatDefaultsAddon;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.jideoss.ui.FlatJidePainter; import com.formdev.flatlaf.jideoss.ui.FlatJidePainter;
@@ -55,8 +56,8 @@ public class FlatJideOssDefaultsAddon
public void afterDefaultsLoading( LookAndFeel laf, UIDefaults defaults ) { public void afterDefaultsLoading( LookAndFeel laf, UIDefaults defaults ) {
// TristateCheckBox // TristateCheckBox
defaults.put( "TristateCheckBox.icon", null ); defaults.put( "TristateCheckBox.icon", null );
defaults.put( "TristateCheckBox.setMixed.clientProperty", new Object[] { "JButton.selectedState", "indeterminate" } ); defaults.put( "TristateCheckBox.setMixed.clientProperty", new Object[] { FlatClientProperties.SELECTED_STATE, FlatClientProperties.SELECTED_STATE_INDETERMINATE } );
defaults.put( "TristateCheckBox.clearMixed.clientProperty", new Object[] { "JButton.selectedState", null } ); defaults.put( "TristateCheckBox.clearMixed.clientProperty", new Object[] { FlatClientProperties.SELECTED_STATE, null } );
} }
@Override @Override

View File

@@ -309,6 +309,8 @@ public class FlatWindowsNativeWindowBorder
WM_ENTERSIZEMOVE = 0x0231, WM_ENTERSIZEMOVE = 0x0231,
WM_EXITSIZEMOVE = 0x0232, WM_EXITSIZEMOVE = 0x0232,
WM_DPICHANGED = 0x02E0,
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320; WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;
// WM_SIZE wParam // WM_SIZE wParam
@@ -501,6 +503,22 @@ public class FlatWindowsNativeWindowBorder
isMoving = true; isMoving = true;
break; break;
case WM_DPICHANGED:
LRESULT lResult = User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam );
// if window is maximized and DPI/scaling changed, then Windows
// does not send a subsequent WM_SIZE message and Java window bounds,
// which depend on scale factor, are not updated
boolean isMaximized = User32Ex.INSTANCE.IsZoomed( hwnd );
if( isMaximized ) {
MyRECT r = new MyRECT( new Pointer( lParam.longValue() ) );
int width = r.right - r.left;
int height = r.bottom - r.top;
User32Ex.INSTANCE.CallWindowProc( defaultWndProc, hwnd, WM_SIZE, new WPARAM( SIZE_MAXIMIZED ), MAKELPARAM( width, height ) );
}
return lResult;
case WM_ERASEBKGND: case WM_ERASEBKGND:
// do not erase background while the user is moving the window, // do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+ // otherwise there may be rendering artifacts on HiDPI screens with Java 9+
@@ -818,6 +836,13 @@ public class FlatWindowsNativeWindowBorder
return (low & 0xffff) | ((high & 0xffff) << 16); return (low & 0xffff) | ((high & 0xffff) << 16);
} }
/**
* Same implementation as MAKELPARAM(l, h) macro in winuser.h.
*/
private LPARAM MAKELPARAM( int low, int high ) {
return new LPARAM( MAKELONG( low, high ) );
}
/** /**
* Same implementation as RGB(r,g,b) macro in wingdi.h. * Same implementation as RGB(r,g,b) macro in wingdi.h.
*/ */
@@ -937,6 +962,23 @@ public class FlatWindowsNativeWindowBorder
} }
} }
//---- class MyRECT -------------------------------------------------------
@FieldOrder( { "left", "top", "right", "bottom" } )
public static class MyRECT
extends Structure
{
public int left;
public int top;
public int right;
public int bottom;
public MyRECT( Pointer pointer ) {
super( pointer );
read();
}
}
//---- class MENUITEMINFO ------------------------------------------------- //---- class MENUITEMINFO -------------------------------------------------
@FieldOrder( { "cbSize", "fMask", "fType", "fState", "wID", "hSubMenu", @FieldOrder( { "cbSize", "fMask", "fType", "fState", "wID", "hSubMenu",

View File

@@ -5,12 +5,15 @@ This sub-project contains the source code for the FlatLaf Linux native library.
The native library can be built only on Linux and requires a C++ compiler. The native library can be built only on Linux and requires a C++ compiler.
The native library is available for following CPU architectures: `x86_64` (or
`amd64`) and `arm64` (or `aarch64`).
To be able to build FlatLaf on any platform, and without C++ compiler, the To be able to build FlatLaf on any platform, and without C++ compiler, the
pre-built native library is checked into Git at pre-built native libraries are checked into Git at
[flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/](https://github.com/JFormDesigner/FlatLaf/tree/main/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives). [flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/](https://github.com/JFormDesigner/FlatLaf/tree/main/flatlaf-core/src/main/resources/com/formdev/flatlaf/natives).
The native library was built on a GitHub server with the help of GitHub Actions. The native libraries were built on a GitHub server with the help of GitHub
See: Actions. See:
[Native Libraries](https://github.com/JFormDesigner/FlatLaf/actions/workflows/natives.yml) [Native Libraries](https://github.com/JFormDesigner/FlatLaf/actions/workflows/natives.yml)
workflow. Then the produced Artifacts ZIP was downloaded and the native library workflow. Then the produced Artifacts ZIP was downloaded and the native library
checked into Git. checked into Git.
@@ -18,19 +21,27 @@ checked into Git.
## Development ## Development
To build the library on Linux, some packages needs to be installed. To build the library on Linux, some packages needs to be installed:
- `build-essential` - GCC and development tools
- `libxt-dev` - X11 toolkit development headers
- `g++-aarch64-linux-gnu` - GNU C++ compiler for the arm64 architecture (only on
x86_64 Linux for cross-compiling for arm64 architecture)
### Ubuntu ### Ubuntu
`build-essential` contains GCC and development tools. `libxt-dev` contains the
X11 toolkit development headers.
~~~ ~~~
sudo apt update sudo apt update
sudo apt install build-essential libxt-dev sudo apt install build-essential libxt-dev
~~~ ~~~
Only on x86_64 Linux for cross-compiling for arm64 architecture:
~~~
sudo apt install g++-aarch64-linux-gnu
~~~
### CentOS ### CentOS

View File

@@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
import java.io.FileOutputStream
plugins { plugins {
`cpp-library` `cpp-library`
`flatlaf-cpp-library` `flatlaf-cpp-library`
@@ -28,11 +30,14 @@ flatlafJniHeaders {
} }
library { library {
targetMachines = listOf( machines.linux.x86_64 ) targetMachines = listOf(
machines.linux.x86_64,
machines.linux.architecture( "aarch64" ),
)
} }
var javaHome = System.getProperty( "java.home" ) var javaHome = System.getProperty( "java.home" )
if( javaHome.endsWith( "jre" ) ) if( javaHome.endsWith( "jre" ) && !file( "${javaHome}/include" ).exists() )
javaHome += "/.." javaHome += "/.."
tasks { tasks {
@@ -40,8 +45,16 @@ tasks {
group = "build" group = "build"
description = "Builds natives" description = "Builds natives"
if( org.gradle.internal.os.OperatingSystem.current().isLinux ) if( org.gradle.internal.os.OperatingSystem.current().isLinux ) {
dependsOn( "linkRelease" ) val osArch = System.getProperty( "os.arch" )
if( osArch == "amd64" ) {
dependsOn( "linkReleaseX86-64" )
if( file( "/usr/bin/aarch64-linux-gnu-gcc" ).exists() )
dependsOn( "linkCrossAarch64" )
}
if( osArch == "aarch64" )
dependsOn( "linkReleaseAarch64" )
}
} }
withType<CppCompile>().configureEach { withType<CppCompile>().configureEach {
@@ -67,7 +80,7 @@ tasks {
onlyIf { name.contains( "Release" ) } onlyIf { name.contains( "Release" ) }
val nativesDir = project( ":flatlaf-core" ).projectDir.resolve( "src/main/resources/com/formdev/flatlaf/natives" ) val nativesDir = project( ":flatlaf-core" ).projectDir.resolve( "src/main/resources/com/formdev/flatlaf/natives" )
val libraryName = "libflatlaf-linux-x86_64.so" val libraryName = if( name.contains( "X86-64" ) ) "libflatlaf-linux-x86_64.so" else "libflatlaf-linux-arm64.so"
val jawt = "jawt" val jawt = "jawt"
var jawtPath = "${javaHome}/lib" var jawtPath = "${javaHome}/lib"
if( JavaVersion.current() == JavaVersion.VERSION_1_8 ) if( JavaVersion.current() == JavaVersion.VERSION_1_8 )
@@ -85,8 +98,103 @@ tasks {
copy { copy {
from( linkedFile ) from( linkedFile )
into( nativesDir ) into( nativesDir )
rename( "libflatlaf-natives-linux.so", libraryName ) rename( linkedFile.get().asFile.name, libraryName )
}
// dump( linkedFile.asFile.get(), true )
}
}
if( org.gradle.internal.os.OperatingSystem.current().isLinux &&
System.getProperty( "os.arch" ) == "amd64" &&
file( "/usr/bin/aarch64-linux-gnu-gcc" ).exists() )
{
register<Exec>( "compileCrossAarch64Cpp" ) {
val include = layout.projectDirectory.dir( "src/main/headers" )
val src = layout.projectDirectory.dir( "src/main/cpp" )
workingDir = file( layout.buildDirectory.dir( "obj/main/release/aarch64-cross" ) )
doFirst {
workingDir.mkdirs()
}
commandLine = listOf(
"aarch64-linux-gnu-gcc",
"-c",
"-fPIC",
"-fvisibility=hidden",
"-O3",
"-I", "${javaHome}/include",
"-I", "${javaHome}/include/linux",
"-I", "$include",
"$src/ApiVersion.cpp",
"$src/X11WmUtils.cpp",
)
}
register<Exec>( "linkCrossAarch64" ) {
dependsOn( "compileCrossAarch64Cpp" )
val nativesDir = project( ":flatlaf-core" ).projectDir.resolve( "src/main/resources/com/formdev/flatlaf/natives" )
val libraryName = "libflatlaf-linux-arm64.so"
val outDir = file( layout.buildDirectory.dir( "lib/main/release/aarch64-cross" ) )
val objDir = file( layout.buildDirectory.dir( "obj/main/release/aarch64-cross" ) )
doFirst {
outDir.mkdirs()
}
commandLine = listOf(
"aarch64-linux-gnu-gcc",
"-shared",
"-Wl,-soname,$libraryName",
"-o", "$outDir/$libraryName",
"$objDir/ApiVersion.o",
"$objDir/X11WmUtils.o",
"-L${layout.projectDirectory}/lib/aarch64",
"-ljawt",
)
doLast {
// copy shared library to flatlaf-core resources
copy {
from( "$outDir/$libraryName" )
into( nativesDir )
}
// dump( file( "$outDir/$libraryName" ), false )
} }
} }
} }
} }
/*dump
interface InjectedExecOps { @get:Inject val execOps: ExecOperations }
val injected = project.objects.newInstance<InjectedExecOps>()
fun dump( dylib: File, disassemble: Boolean ) {
val dylibDir = dylib.parent
injected.execOps.exec { commandLine( "size", dylib ); standardOutput = FileOutputStream( "$dylibDir/size.txt" ) }
injected.execOps.exec {
commandLine( "objdump",
// commands
"--archive-headers",
"--section-headers",
"--private-headers",
"--reloc",
"--dynamic-reloc",
"--syms",
// files
dylib )
standardOutput = FileOutputStream( "$dylibDir/objdump.txt" )
}
if( disassemble )
injected.execOps.exec { commandLine( "objdump", "--disassemble-all", dylib ); standardOutput = FileOutputStream( "$dylibDir/disassemble.txt" ) }
injected.execOps.exec { commandLine( "objdump", "--full-contents", dylib ); standardOutput = FileOutputStream( "$dylibDir/full-contents.txt" ) }
injected.execOps.exec { commandLine( "hexdump", dylib ); standardOutput = FileOutputStream( "$dylibDir/hexdump.txt" ) }
}
dump*/

View File

@@ -0,0 +1,4 @@
Contains libraries used to compile FlatLaf native libraries.
- `aarch64/libjawt.so` is `<jdk>/lib/libjawt.so` from Eclipse Temurin 11.0.25+9 aarch64,
which is required to cross build aarch64/arm64 .so on x86_64

View File

@@ -43,6 +43,9 @@ var javaHome = System.getProperty( "java.home" )
if( javaHome.endsWith( "jre" ) ) if( javaHome.endsWith( "jre" ) )
javaHome += "/.." javaHome += "/.."
interface InjectedExecOps { @get:Inject val execOps: ExecOperations }
val injected = project.objects.newInstance<InjectedExecOps>()
tasks { tasks {
register( "build-natives" ) { register( "build-natives" ) {
group = "build" group = "build"
@@ -95,21 +98,21 @@ tasks {
doLast { doLast {
// sign shared library // sign shared library
// exec { commandLine( "codesign", "-s", "FormDev Software GmbH", "--timestamp", "${linkedFile.asFile.get()}" ) } // injected.execOps.exec { commandLine( "codesign", "-s", "FormDev Software GmbH", "--timestamp", "${linkedFile.asFile.get()}" ) }
// copy shared library to flatlaf-core resources // copy shared library to flatlaf-core resources
copy { copy {
from( linkedFile ) from( linkedFile )
into( nativesDir ) into( nativesDir )
rename( "libflatlaf-natives-macos.dylib", libraryName ) rename( linkedFile.get().asFile.name, libraryName )
} }
/*dump /*dump
val dylib = linkedFile.asFile.get() val dylib = linkedFile.asFile.get()
val dylibDir = dylib.parent val dylibDir = dylib.parent
exec { commandLine( "size", dylib ) } injected.execOps.exec { commandLine( "size", dylib ); standardOutput = FileOutputStream( "$dylibDir/size.txt" ) }
exec { commandLine( "size", "-m", dylib ) } injected.execOps.exec { commandLine( "size", "-m", dylib ); standardOutput = FileOutputStream( "$dylibDir/size-m.txt" ) }
exec { injected.execOps.exec {
commandLine( "objdump", commandLine( "objdump",
// commands // commands
"--archive-headers", "--archive-headers",
@@ -127,8 +130,8 @@ tasks {
dylib ) dylib )
standardOutput = FileOutputStream( "$dylibDir/objdump.txt" ) standardOutput = FileOutputStream( "$dylibDir/objdump.txt" )
} }
exec { commandLine( "objdump", "--disassemble-all", dylib ); standardOutput = FileOutputStream( "$dylibDir/disassemble.txt" ) } injected.execOps.exec { commandLine( "objdump", "--disassemble-all", dylib ); standardOutput = FileOutputStream( "$dylibDir/disassemble.txt" ) }
exec { commandLine( "objdump", "--full-contents", dylib ); standardOutput = FileOutputStream( "$dylibDir/full-contents.txt" ) } injected.execOps.exec { commandLine( "objdump", "--full-contents", dylib ); standardOutput = FileOutputStream( "$dylibDir/full-contents.txt" ) }
dump*/ dump*/
} }
} }

View File

@@ -29,15 +29,21 @@
#endif #endif
#define JNI_COCOA_TRY() \
@try {
#define JNI_COCOA_CATCH() \
} @catch( NSException *ex ) { \
NSLog( @"Exception: %@\nReason: %@\nUser Info: %@\nStack: %@", \
[ex name], [ex reason], [ex userInfo], [ex callStackSymbols] ); \
}
#define JNI_COCOA_ENTER() \ #define JNI_COCOA_ENTER() \
@autoreleasepool { \ @autoreleasepool { \
@try { JNI_COCOA_TRY()
#define JNI_COCOA_EXIT() \ #define JNI_COCOA_EXIT() \
} @catch( NSException *ex ) { \ JNI_COCOA_CATCH() \
NSLog( @"Exception: %@\nReason: %@\nUser Info: %@\nStack: %@", \
[ex name], [ex reason], [ex userInfo], [ex callStackSymbols] ); \
} \
} }

View File

@@ -100,10 +100,13 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
return FALSE; return FALSE;
[FlatJNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ [FlatJNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
JNI_COCOA_TRY()
nsWindow.hasShadow = YES; nsWindow.hasShadow = YES;
nsWindow.contentView.wantsLayer = YES; nsWindow.contentView.wantsLayer = YES;
nsWindow.contentView.layer.cornerRadius = radius; nsWindow.contentView.layer.cornerRadius = radius;
nsWindow.contentView.layer.masksToBounds = YES; nsWindow.contentView.layer.masksToBounds = YES;
nsWindow.contentView.layer.opaque = NO;
nsWindow.contentView.layer.borderWidth = borderWidth; nsWindow.contentView.layer.borderWidth = borderWidth;
if( borderWidth > 0 ) { if( borderWidth > 0 ) {
@@ -120,6 +123,8 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
[nsWindow.contentView.layer removeAllAnimations]; [nsWindow.contentView.layer removeAllAnimations];
[nsWindow invalidateShadow]; [nsWindow invalidateShadow];
JNI_COCOA_CATCH()
}]; }];
return TRUE; return TRUE;
@@ -157,6 +162,8 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
WindowData* windowData = getWindowData( nsWindow, true ); WindowData* windowData = getWindowData( nsWindow, true );
[FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ [FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
JNI_COCOA_TRY()
// NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] ); // NSLog( @"\n%@\n\n", [nsWindow.contentView.superview _subtreeDescription] );
// add/remove toolbar // add/remove toolbar
@@ -235,6 +242,8 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
windowData.didExitFullScreenObserver = nil; windowData.didExitFullScreenObserver = nil;
} }
} }
JNI_COCOA_CATCH()
}]; }];
return TRUE; return TRUE;

View File

@@ -8,8 +8,8 @@ The native library can be built only on Windows and requires a C++ compiler.
Tested with Microsoft Visual C++ (MSVC) 2019 and 2022 (comes with Visual Studio Tested with Microsoft Visual C++ (MSVC) 2019 and 2022 (comes with Visual Studio
2019 and 2022). 2019 and 2022).
The native library is available for folloging CPU architectures: `x86_64` (or The native library is available for following CPU architectures: `x86_64` (or
`amd64`), `x86` and `arm64`. `amd64`), `x86` and `arm64` (or `aarch64`).
To be able to build FlatLaf on any platform, and without C++ compiler, the To be able to build FlatLaf on any platform, and without C++ compiler, the
pre-built DLLs are checked into Git at pre-built DLLs are checked into Git at
@@ -19,3 +19,32 @@ The DLLs were built on a GitHub server with the help of GitHub Actions. See:
[Native Libraries](https://github.com/JFormDesigner/FlatLaf/actions/workflows/natives.yml) [Native Libraries](https://github.com/JFormDesigner/FlatLaf/actions/workflows/natives.yml)
workflow. Then the produced Artifacts ZIP was downloaded, signed DLLs with workflow. Then the produced Artifacts ZIP was downloaded, signed DLLs with
FormDev Software code signing certificate and committed the DLLs to Git. FormDev Software code signing certificate and committed the DLLs to Git.
## Development
To build the library on Windows using Gradle, (parts of)
[Visual Studio Community
2022](https://visualstudio.microsoft.com/downloads/)
needs to be installed. After downloading and running `VisualStudioSetup.exe` the
**Visual Studio Installer** is installed and started. Once running, it shows the
**Workloads** tab that allows you to install additional packages. Either choose
**Desktop development with C++**, or to save some disk space switch to the
**Single Components** tab and choose following components (newest versions):
- MSVC v143 - VS 2022 C++ x64/x86 Buildtools
- MSVC v143 - VS 2022 C++ ARM64/ARM64EC Buildtools
- Windows 11 SDK
Note that the Visual Studio Installer shows many similar named components for
MSVC. Make sure to choose exactly those components listed above.
Using
[Build Tools for Visual Studio 2022](https://visualstudio.microsoft.com/downloads/#remote-tools-for-visual-studio-2022)
(installs only compiler and SDKs) instead of
[Visual Studio Community
2022](https://visualstudio.microsoft.com/downloads/)
does not work with Gradle.
[Visual Studio Code](https://code.visualstudio.com/) with **C/C++** extension
can be used for C++ code editing.

View File

@@ -91,7 +91,7 @@ tasks {
copy { copy {
from( linkedFile ) from( linkedFile )
into( nativesDir ) into( nativesDir )
rename( "flatlaf-natives-windows.dll", libraryName ) rename( linkedFile.get().asFile.name, libraryName )
} }
} }
} }

View File

@@ -288,6 +288,23 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
isMoving = true; isMoving = true;
break; break;
case WM_DPICHANGED: {
LRESULT lResult = ::CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam );
// if window is maximized and DPI/scaling changed, then Windows
// does not send a subsequent WM_SIZE message and Java window bounds,
// which depend on scale factor, are not updated
bool isMaximized = ::IsZoomed( hwnd );
if( isMaximized ) {
RECT* r = reinterpret_cast<RECT*>( lParam );
int width = r->right - r->left;
int height = r->bottom - r->top;
::CallWindowProc( defaultWndProc, hwnd, WM_SIZE, SIZE_MAXIMIZED, MAKELPARAM( width, height ) );
}
return lResult;
}
case WM_ERASEBKGND: case WM_ERASEBKGND:
// do not erase background while the user is moving the window, // do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+ // otherwise there may be rendering artifacts on HiDPI screens with Java 9+

View File

@@ -30,12 +30,26 @@ HWND getWindowHandle( JNIEnv* env, jobject window );
//---- Utility ---------------------------------------------------------------- //---- Utility ----------------------------------------------------------------
typedef LONG (WINAPI *RtlGetVersion_Type)( OSVERSIONINFO* );
extern "C" extern "C"
JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_getOSBuildNumberImpl JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_getOSBuildNumberImpl
( JNIEnv* env, jclass cls ) ( JNIEnv* env, jclass cls )
{ {
OSVERSIONINFO info; OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof( info ); info.dwOSVersionInfoSize = sizeof( info );
info.dwBuildNumber = 0;
// use RtlGetVersion for the case that app manifest does not specify Windows 10+ compatibility
// https://www.codeproject.com/Articles/5336372/Windows-Version-Detection
HMODULE ntdllModule = ::GetModuleHandleA( "ntdll.dll" );
if( ntdllModule != NULL ) {
RtlGetVersion_Type pRtlGetVersion = (RtlGetVersion_Type) ::GetProcAddress( ntdllModule, "RtlGetVersion" );
if( pRtlGetVersion != NULL && pRtlGetVersion( &info ) == 0 )
return info.dwBuildNumber;
}
// fallback
if( !::GetVersionEx( &info ) ) if( !::GetVersionEx( &info ) )
return 0; return 0;
return info.dwBuildNumber; return info.dwBuildNumber;

View File

@@ -1,12 +1,11 @@
- Java 1.8.0_202 - Java 1.8.0_202
+ Java 1.8.0_292 + Java 1.8.0_322
- OS Windows 10 - OS Windows 10
+ OS Mac OS X + OS Mac OS X
#---- ComboBox ---- #---- ComboBox ----
+ ComboBox.roundedBorderWidth 1
+ ComboBox.showPopupOnNavigation true + ComboBox.showPopupOnNavigation true
@@ -47,16 +46,6 @@
+ OptionPane.isYesLast true + OptionPane.isYesLast true
#---- Popup ----
+ Popup.roundedBorderWidth 1
#---- PopupMenu ----
+ PopupMenu.roundedBorderWidth 1
#---- ProgressBar ---- #---- ProgressBar ----
- ProgressBar.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI] - ProgressBar.font [active] Segoe UI plain 10 javax.swing.plaf.FontUIResource [UI]
@@ -88,11 +77,6 @@
- TitlePane.small.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI] - TitlePane.small.font [active] Segoe UI plain 11 javax.swing.plaf.FontUIResource [UI]
+ TitlePane.small.font [active] Helvetica Neue plain 12 javax.swing.plaf.FontUIResource [UI] + TitlePane.small.font [active] Helvetica Neue plain 12 javax.swing.plaf.FontUIResource [UI]
#---- ToolTip ----
+ ToolTip.roundedBorderWidth 1
- defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI] - defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI]
+ defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI] + defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI]

View File

@@ -222,6 +222,7 @@ ComboBox.minimumWidth 72
ComboBox.noActionOnKeyNavigation false ComboBox.noActionOnKeyNavigation false
ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.roundedBorderWidth 1
ComboBox.selectionArc 0 ComboBox.selectionArc 0
ComboBox.selectionBackground #4b6eaf HSL 219 40 49 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #4b6eaf HSL 219 40 49 javax.swing.plaf.ColorUIResource [UI]
ComboBox.selectionForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
@@ -744,6 +745,7 @@ Popup.dropShadowColor #000000 HSL 0 0 0 javax.swing.plaf.Colo
Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI] Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI]
Popup.dropShadowOpacity 0.25 Popup.dropShadowOpacity 0.25
Popup.dropShadowPainted true Popup.dropShadowPainted true
Popup.roundedBorderWidth 1
#---- PopupMenu ---- #---- PopupMenu ----
@@ -757,6 +759,7 @@ PopupMenu.consumeEventOnClose false
PopupMenu.font [active] $defaultFont [UI] PopupMenu.font [active] $defaultFont [UI]
PopupMenu.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] PopupMenu.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.hoverScrollArrowBackground #484c4e HSL 200 4 29 javax.swing.plaf.ColorUIResource [UI] PopupMenu.hoverScrollArrowBackground #484c4e HSL 200 4 29 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.roundedBorderWidth 1
PopupMenu.scrollArrowColor #9b9b9b HSL 0 0 61 javax.swing.plaf.ColorUIResource [UI] PopupMenu.scrollArrowColor #9b9b9b HSL 0 0 61 javax.swing.plaf.ColorUIResource [UI]
@@ -1375,6 +1378,7 @@ ToolTip.border [lazy] 4,6,4,6 false com.formdev.flatlaf.ui.F
ToolTip.borderCornerRadius 4 ToolTip.borderCornerRadius 4
ToolTip.font [active] $defaultFont [UI] ToolTip.font [active] $defaultFont [UI]
ToolTip.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] ToolTip.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
ToolTip.roundedBorderWidth 1
#---- ToolTipManager ---- #---- ToolTipManager ----
@@ -1431,6 +1435,7 @@ Tree.showDefaultIcons false
Tree.textBackground #46494b HSL 204 3 28 javax.swing.plaf.ColorUIResource [UI] Tree.textBackground #46494b HSL 204 3 28 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] Tree.textForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000 Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI TreeUI com.formdev.flatlaf.ui.FlatTreeUI

View File

@@ -1,12 +1,14 @@
- Java 1.8.0_202 - Java 1.8.0_202
+ Java 1.8.0_292 + Java 1.8.0_322
- OS Windows 10 - OS Windows 10
+ OS Mac OS X + OS Mac OS X
#---- ComboBox ---- #---- ComboBox ----
- ComboBox.roundedBorderWidth 1
+ ComboBox.roundedBorderWidth 0 + ComboBox.roundedBorderWidth 0
+ ComboBox.showPopupOnNavigation true + ComboBox.showPopupOnNavigation true
@@ -49,11 +51,13 @@
#---- Popup ---- #---- Popup ----
- Popup.roundedBorderWidth 1
+ Popup.roundedBorderWidth 0 + Popup.roundedBorderWidth 0
#---- PopupMenu ---- #---- PopupMenu ----
- PopupMenu.roundedBorderWidth 1
+ PopupMenu.roundedBorderWidth 0 + PopupMenu.roundedBorderWidth 0
@@ -92,6 +96,7 @@
#---- ToolTip ---- #---- ToolTip ----
- ToolTip.roundedBorderWidth 1
+ ToolTip.roundedBorderWidth 0 + ToolTip.roundedBorderWidth 0
- defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI] - defaultFont Segoe UI plain 12 javax.swing.plaf.FontUIResource [UI]
+ defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI] + defaultFont Helvetica Neue plain 13 javax.swing.plaf.FontUIResource [UI]

View File

@@ -226,6 +226,7 @@ ComboBox.minimumWidth 72
ComboBox.noActionOnKeyNavigation false ComboBox.noActionOnKeyNavigation false
ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.roundedBorderWidth 1
ComboBox.selectionArc 0 ComboBox.selectionArc 0
ComboBox.selectionBackground #2675bf HSL 209 67 45 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #2675bf HSL 209 67 45 javax.swing.plaf.ColorUIResource [UI]
ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
@@ -749,6 +750,7 @@ Popup.dropShadowColor #000000 HSL 0 0 0 javax.swing.plaf.Colo
Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI] Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI]
Popup.dropShadowOpacity 0.15 Popup.dropShadowOpacity 0.15
Popup.dropShadowPainted true Popup.dropShadowPainted true
Popup.roundedBorderWidth 1
#---- PopupMenu ---- #---- PopupMenu ----
@@ -762,6 +764,7 @@ PopupMenu.consumeEventOnClose false
PopupMenu.font [active] $defaultFont [UI] PopupMenu.font [active] $defaultFont [UI]
PopupMenu.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI] PopupMenu.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.hoverScrollArrowBackground #e5e5e5 HSL 0 0 90 javax.swing.plaf.ColorUIResource [UI] PopupMenu.hoverScrollArrowBackground #e5e5e5 HSL 0 0 90 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.roundedBorderWidth 1
PopupMenu.scrollArrowColor #666666 HSL 0 0 40 javax.swing.plaf.ColorUIResource [UI] PopupMenu.scrollArrowColor #666666 HSL 0 0 40 javax.swing.plaf.ColorUIResource [UI]
@@ -1380,6 +1383,7 @@ ToolTip.border [lazy] 4,6,4,6 false com.formdev.flatlaf.ui.F
ToolTip.borderCornerRadius 4 ToolTip.borderCornerRadius 4
ToolTip.font [active] $defaultFont [UI] ToolTip.font [active] $defaultFont [UI]
ToolTip.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI] ToolTip.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
ToolTip.roundedBorderWidth 1
#---- ToolTipManager ---- #---- ToolTipManager ----
@@ -1436,6 +1440,7 @@ Tree.showDefaultIcons false
Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI] Tree.textForeground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000 Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI TreeUI com.formdev.flatlaf.ui.FlatTreeUI

View File

@@ -228,6 +228,7 @@ ComboBox.noActionOnKeyNavigation false
ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.popupBackground #323232 HSL 0 0 20 javax.swing.plaf.ColorUIResource [UI] ComboBox.popupBackground #323232 HSL 0 0 20 javax.swing.plaf.ColorUIResource [UI]
ComboBox.popupInsets 5,0,5,0 javax.swing.plaf.InsetsUIResource [UI] ComboBox.popupInsets 5,0,5,0 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.roundedBorderWidth 1
ComboBox.selectionArc 8 ComboBox.selectionArc 8
ComboBox.selectionBackground #1458b8 HSL 215 80 40 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #1458b8 HSL 215 80 40 javax.swing.plaf.ColorUIResource [UI]
ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
@@ -752,6 +753,7 @@ Popup.dropShadowColor #000000 HSL 0 0 0 javax.swing.plaf.Colo
Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI] Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI]
Popup.dropShadowOpacity 0.25 Popup.dropShadowOpacity 0.25
Popup.dropShadowPainted true Popup.dropShadowPainted true
Popup.roundedBorderWidth 1
#---- PopupMenu ---- #---- PopupMenu ----
@@ -765,6 +767,7 @@ PopupMenu.consumeEventOnClose false
PopupMenu.font [active] $defaultFont [UI] PopupMenu.font [active] $defaultFont [UI]
PopupMenu.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI] PopupMenu.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.hoverScrollArrowBackground #2b2b2b HSL 0 0 17 javax.swing.plaf.ColorUIResource [UI] PopupMenu.hoverScrollArrowBackground #2b2b2b HSL 0 0 17 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.roundedBorderWidth 1
PopupMenu.scrollArrowColor #b7b7b7 HSL 0 0 72 javax.swing.plaf.ColorUIResource [UI] PopupMenu.scrollArrowColor #b7b7b7 HSL 0 0 72 javax.swing.plaf.ColorUIResource [UI]
@@ -1385,6 +1388,7 @@ ToolTip.border [lazy] 4,6,4,6 false com.formdev.flatlaf.ui.F
ToolTip.borderCornerRadius 4 ToolTip.borderCornerRadius 4
ToolTip.font [active] $defaultFont [UI] ToolTip.font [active] $defaultFont [UI]
ToolTip.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI] ToolTip.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
ToolTip.roundedBorderWidth 1
#---- ToolTipManager ---- #---- ToolTipManager ----
@@ -1441,6 +1445,7 @@ Tree.showDefaultIcons false
Tree.textBackground #282828 HSL 0 0 16 javax.swing.plaf.ColorUIResource [UI] Tree.textBackground #282828 HSL 0 0 16 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI] Tree.textForeground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000 Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI TreeUI com.formdev.flatlaf.ui.FlatTreeUI

View File

@@ -232,6 +232,7 @@ ComboBox.noActionOnKeyNavigation false
ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.popupBackground #ececec HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI] ComboBox.popupBackground #ececec HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI]
ComboBox.popupInsets 5,0,5,0 javax.swing.plaf.InsetsUIResource [UI] ComboBox.popupInsets 5,0,5,0 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.roundedBorderWidth 1
ComboBox.selectionArc 8 ComboBox.selectionArc 8
ComboBox.selectionBackground #3d9aff HSL 211 100 62 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #3d9aff HSL 211 100 62 javax.swing.plaf.ColorUIResource [UI]
ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
@@ -756,6 +757,7 @@ Popup.dropShadowColor #000000 HSL 0 0 0 javax.swing.plaf.Colo
Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI] Popup.dropShadowInsets -4,-4,4,4 javax.swing.plaf.InsetsUIResource [UI]
Popup.dropShadowOpacity 0.15 Popup.dropShadowOpacity 0.15
Popup.dropShadowPainted true Popup.dropShadowPainted true
Popup.roundedBorderWidth 1
#---- PopupMenu ---- #---- PopupMenu ----
@@ -769,6 +771,7 @@ PopupMenu.consumeEventOnClose false
PopupMenu.font [active] $defaultFont [UI] PopupMenu.font [active] $defaultFont [UI]
PopupMenu.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI] PopupMenu.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.hoverScrollArrowBackground #e9e9e9 HSL 0 0 91 javax.swing.plaf.ColorUIResource [UI] PopupMenu.hoverScrollArrowBackground #e9e9e9 HSL 0 0 91 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.roundedBorderWidth 1
PopupMenu.scrollArrowColor #7d7d7d HSL 0 0 49 javax.swing.plaf.ColorUIResource [UI] PopupMenu.scrollArrowColor #7d7d7d HSL 0 0 49 javax.swing.plaf.ColorUIResource [UI]
@@ -1389,6 +1392,7 @@ ToolTip.border [lazy] 4,6,4,6 false com.formdev.flatlaf.ui.F
ToolTip.borderCornerRadius 4 ToolTip.borderCornerRadius 4
ToolTip.font [active] $defaultFont [UI] ToolTip.font [active] $defaultFont [UI]
ToolTip.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI] ToolTip.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
ToolTip.roundedBorderWidth 1
#---- ToolTipManager ---- #---- ToolTipManager ----
@@ -1445,6 +1449,7 @@ Tree.showDefaultIcons false
Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] Tree.textBackground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI] Tree.textForeground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000 Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI TreeUI com.formdev.flatlaf.ui.FlatTreeUI

View File

@@ -254,6 +254,7 @@ ComboBox.noActionOnKeyNavigation false
ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI] ComboBox.padding 2,6,2,6 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.popupBackground #ffffcc HSL 60 100 90 javax.swing.plaf.ColorUIResource [UI] ComboBox.popupBackground #ffffcc HSL 60 100 90 javax.swing.plaf.ColorUIResource [UI]
ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] ComboBox.popupInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
ComboBox.roundedBorderWidth 1
ComboBox.selectionArc 0 ComboBox.selectionArc 0
ComboBox.selectionBackground #00aa00 HSL 120 100 33 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionBackground #00aa00 HSL 120 100 33 javax.swing.plaf.ColorUIResource [UI]
ComboBox.selectionForeground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI] ComboBox.selectionForeground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI]
@@ -782,6 +783,7 @@ Popup.dropShadowColor #00ff00 HSL 120 100 50 javax.swing.plaf.Colo
Popup.dropShadowInsets -6,6,6,6 javax.swing.plaf.InsetsUIResource [UI] Popup.dropShadowInsets -6,6,6,6 javax.swing.plaf.InsetsUIResource [UI]
Popup.dropShadowOpacity 0.5 Popup.dropShadowOpacity 0.5
Popup.dropShadowPainted true Popup.dropShadowPainted true
Popup.roundedBorderWidth 1
#---- PopupMenu ---- #---- PopupMenu ----
@@ -795,6 +797,7 @@ PopupMenu.consumeEventOnClose false
PopupMenu.font [active] $defaultFont [UI] PopupMenu.font [active] $defaultFont [UI]
PopupMenu.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] PopupMenu.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.hoverScrollArrowBackground #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI] PopupMenu.hoverScrollArrowBackground #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI]
PopupMenu.roundedBorderWidth 1
PopupMenu.scrollArrowColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI] PopupMenu.scrollArrowColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
@@ -1438,6 +1441,7 @@ ToolTip.border [lazy] line: #000000 HSL 0 0 0 java.awt
ToolTip.borderCornerRadius 4 ToolTip.borderCornerRadius 4
ToolTip.font [active] $defaultFont [UI] ToolTip.font [active] $defaultFont [UI]
ToolTip.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] ToolTip.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
ToolTip.roundedBorderWidth 1
#---- ToolTipManager ---- #---- ToolTipManager ----
@@ -1495,6 +1499,7 @@ Tree.showDefaultIcons false
Tree.textBackground #fff0ff HSL 300 100 97 javax.swing.plaf.ColorUIResource [UI] Tree.textBackground #fff0ff HSL 300 100 97 javax.swing.plaf.ColorUIResource [UI]
Tree.textForeground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] Tree.textForeground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
Tree.timeFactor 1000 Tree.timeFactor 1000
Tree.wideCellRenderer false
Tree.wideSelection true Tree.wideSelection true
TreeUI com.formdev.flatlaf.ui.FlatTreeUI TreeUI com.formdev.flatlaf.ui.FlatTreeUI

View File

@@ -198,17 +198,17 @@ public class FlatComponentStateTest
//---- label11 ---- //---- label11 ----
label11.setText("JButton"); label11.setText("JButton");
label11.putClientProperty("FlatLaf.styleClass", "h3"); label11.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(label11, "cell 1 0 2 1"); add(label11, "cell 1 0 2 1");
//---- label12 ---- //---- label12 ----
label12.setText("JToggleButton"); label12.setText("JToggleButton");
label12.putClientProperty("FlatLaf.styleClass", "h3"); label12.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(label12, "cell 5 0 3 1"); add(label12, "cell 5 0 3 1");
//---- label32 ---- //---- label32 ----
label32.setText("Help Button"); label32.setText("Help Button");
label32.putClientProperty("FlatLaf.styleClass", "h3"); label32.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(label32, "cell 9 0 2 1"); add(label32, "cell 9 0 2 1");
//---- label5 ---- //---- label5 ----
@@ -257,26 +257,26 @@ public class FlatComponentStateTest
//---- testStateButton1 ---- //---- testStateButton1 ----
testStateButton1.setText("text"); testStateButton1.setText("text");
testStateButton1.putClientProperty("JComponent.minimumWidth", 0); testStateButton1.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton1, "cell 1 2"); add(testStateButton1, "cell 1 2");
//---- testStateButton7 ---- //---- testStateButton7 ----
testStateButton7.setText("text"); testStateButton7.setText("text");
testStateButton7.setStateDefault(true); testStateButton7.setStateDefault(true);
testStateButton7.putClientProperty("JComponent.minimumWidth", 0); testStateButton7.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton7, "cell 2 2"); add(testStateButton7, "cell 2 2");
//---- testStateButton4 ---- //---- testStateButton4 ----
testStateButton4.setText("text"); testStateButton4.setText("text");
testStateButton4.setStateFocused(true); testStateButton4.setStateFocused(true);
testStateButton4.putClientProperty("JComponent.minimumWidth", 0); testStateButton4.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton4, "cell 3 2"); add(testStateButton4, "cell 3 2");
//---- testStateButton10 ---- //---- testStateButton10 ----
testStateButton10.setText("text"); testStateButton10.setText("text");
testStateButton10.setStateFocused(true); testStateButton10.setStateFocused(true);
testStateButton10.setStateDefault(true); testStateButton10.setStateDefault(true);
testStateButton10.putClientProperty("JComponent.minimumWidth", 0); testStateButton10.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton10, "cell 4 2"); add(testStateButton10, "cell 4 2");
//---- testStateToggleButton1 ---- //---- testStateToggleButton1 ----
@@ -300,14 +300,14 @@ public class FlatComponentStateTest
add(testStateToggleButton12, "cell 8 2"); add(testStateToggleButton12, "cell 8 2");
//---- testStateButton15 ---- //---- testStateButton15 ----
testStateButton15.putClientProperty("JComponent.minimumWidth", 0); testStateButton15.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton15.putClientProperty("JButton.buttonType", "help"); testStateButton15.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton15, "cell 9 2"); add(testStateButton15, "cell 9 2");
//---- testStateButton19 ---- //---- testStateButton19 ----
testStateButton19.setStateFocused(true); testStateButton19.setStateFocused(true);
testStateButton19.putClientProperty("JComponent.minimumWidth", 0); testStateButton19.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton19.putClientProperty("JButton.buttonType", "help"); testStateButton19.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton19, "cell 10 2"); add(testStateButton19, "cell 10 2");
//---- label2 ---- //---- label2 ----
@@ -317,21 +317,21 @@ public class FlatComponentStateTest
//---- testStateButton2 ---- //---- testStateButton2 ----
testStateButton2.setText("text"); testStateButton2.setText("text");
testStateButton2.setStateHover(true); testStateButton2.setStateHover(true);
testStateButton2.putClientProperty("JComponent.minimumWidth", 0); testStateButton2.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton2, "cell 1 3"); add(testStateButton2, "cell 1 3");
//---- testStateButton8 ---- //---- testStateButton8 ----
testStateButton8.setText("text"); testStateButton8.setText("text");
testStateButton8.setStateHover(true); testStateButton8.setStateHover(true);
testStateButton8.setStateDefault(true); testStateButton8.setStateDefault(true);
testStateButton8.putClientProperty("JComponent.minimumWidth", 0); testStateButton8.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton8, "cell 2 3"); add(testStateButton8, "cell 2 3");
//---- testStateButton5 ---- //---- testStateButton5 ----
testStateButton5.setText("text"); testStateButton5.setText("text");
testStateButton5.setStateHover(true); testStateButton5.setStateHover(true);
testStateButton5.setStateFocused(true); testStateButton5.setStateFocused(true);
testStateButton5.putClientProperty("JComponent.minimumWidth", 0); testStateButton5.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton5, "cell 3 3"); add(testStateButton5, "cell 3 3");
//---- testStateButton11 ---- //---- testStateButton11 ----
@@ -339,7 +339,7 @@ public class FlatComponentStateTest
testStateButton11.setStateHover(true); testStateButton11.setStateHover(true);
testStateButton11.setStateFocused(true); testStateButton11.setStateFocused(true);
testStateButton11.setStateDefault(true); testStateButton11.setStateDefault(true);
testStateButton11.putClientProperty("JComponent.minimumWidth", 0); testStateButton11.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton11, "cell 4 3"); add(testStateButton11, "cell 4 3");
//---- testStateToggleButton2 ---- //---- testStateToggleButton2 ----
@@ -368,15 +368,15 @@ public class FlatComponentStateTest
//---- testStateButton16 ---- //---- testStateButton16 ----
testStateButton16.setStateHover(true); testStateButton16.setStateHover(true);
testStateButton16.putClientProperty("JComponent.minimumWidth", 0); testStateButton16.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton16.putClientProperty("JButton.buttonType", "help"); testStateButton16.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton16, "cell 9 3"); add(testStateButton16, "cell 9 3");
//---- testStateButton20 ---- //---- testStateButton20 ----
testStateButton20.setStateHover(true); testStateButton20.setStateHover(true);
testStateButton20.setStateFocused(true); testStateButton20.setStateFocused(true);
testStateButton20.putClientProperty("JComponent.minimumWidth", 0); testStateButton20.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton20.putClientProperty("JButton.buttonType", "help"); testStateButton20.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton20, "cell 10 3"); add(testStateButton20, "cell 10 3");
//---- label3 ---- //---- label3 ----
@@ -386,21 +386,21 @@ public class FlatComponentStateTest
//---- testStateButton3 ---- //---- testStateButton3 ----
testStateButton3.setText("text"); testStateButton3.setText("text");
testStateButton3.setStatePressed(true); testStateButton3.setStatePressed(true);
testStateButton3.putClientProperty("JComponent.minimumWidth", 0); testStateButton3.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton3, "cell 1 4"); add(testStateButton3, "cell 1 4");
//---- testStateButton9 ---- //---- testStateButton9 ----
testStateButton9.setText("text"); testStateButton9.setText("text");
testStateButton9.setStatePressed(true); testStateButton9.setStatePressed(true);
testStateButton9.setStateDefault(true); testStateButton9.setStateDefault(true);
testStateButton9.putClientProperty("JComponent.minimumWidth", 0); testStateButton9.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton9, "cell 2 4"); add(testStateButton9, "cell 2 4");
//---- testStateButton6 ---- //---- testStateButton6 ----
testStateButton6.setText("text"); testStateButton6.setText("text");
testStateButton6.setStatePressed(true); testStateButton6.setStatePressed(true);
testStateButton6.setStateFocused(true); testStateButton6.setStateFocused(true);
testStateButton6.putClientProperty("JComponent.minimumWidth", 0); testStateButton6.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton6, "cell 3 4"); add(testStateButton6, "cell 3 4");
//---- testStateButton12 ---- //---- testStateButton12 ----
@@ -408,7 +408,7 @@ public class FlatComponentStateTest
testStateButton12.setStatePressed(true); testStateButton12.setStatePressed(true);
testStateButton12.setStateFocused(true); testStateButton12.setStateFocused(true);
testStateButton12.setStateDefault(true); testStateButton12.setStateDefault(true);
testStateButton12.putClientProperty("JComponent.minimumWidth", 0); testStateButton12.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton12, "cell 4 4"); add(testStateButton12, "cell 4 4");
//---- testStateToggleButton3 ---- //---- testStateToggleButton3 ----
@@ -437,15 +437,15 @@ public class FlatComponentStateTest
//---- testStateButton17 ---- //---- testStateButton17 ----
testStateButton17.setStatePressed(true); testStateButton17.setStatePressed(true);
testStateButton17.putClientProperty("JComponent.minimumWidth", 0); testStateButton17.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton17.putClientProperty("JButton.buttonType", "help"); testStateButton17.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton17, "cell 9 4"); add(testStateButton17, "cell 9 4");
//---- testStateButton21 ---- //---- testStateButton21 ----
testStateButton21.setStatePressed(true); testStateButton21.setStatePressed(true);
testStateButton21.setStateFocused(true); testStateButton21.setStateFocused(true);
testStateButton21.putClientProperty("JComponent.minimumWidth", 0); testStateButton21.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton21.putClientProperty("JButton.buttonType", "help"); testStateButton21.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton21, "cell 10 4"); add(testStateButton21, "cell 10 4");
//---- label4 ---- //---- label4 ----
@@ -455,14 +455,14 @@ public class FlatComponentStateTest
//---- testStateButton13 ---- //---- testStateButton13 ----
testStateButton13.setText("text"); testStateButton13.setText("text");
testStateButton13.setEnabled(false); testStateButton13.setEnabled(false);
testStateButton13.putClientProperty("JComponent.minimumWidth", 0); testStateButton13.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton13, "cell 1 5"); add(testStateButton13, "cell 1 5");
//---- testStateButton14 ---- //---- testStateButton14 ----
testStateButton14.setText("text"); testStateButton14.setText("text");
testStateButton14.setEnabled(false); testStateButton14.setEnabled(false);
testStateButton14.setStateDefault(true); testStateButton14.setStateDefault(true);
testStateButton14.putClientProperty("JComponent.minimumWidth", 0); testStateButton14.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testStateButton14, "cell 2 5"); add(testStateButton14, "cell 2 5");
//---- testStateToggleButton4 ---- //---- testStateToggleButton4 ----
@@ -478,8 +478,8 @@ public class FlatComponentStateTest
//---- testStateButton18 ---- //---- testStateButton18 ----
testStateButton18.setEnabled(false); testStateButton18.setEnabled(false);
testStateButton18.putClientProperty("JComponent.minimumWidth", 0); testStateButton18.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
testStateButton18.putClientProperty("JButton.buttonType", "help"); testStateButton18.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(testStateButton18, "cell 9 5"); add(testStateButton18, "cell 9 5");
//---- label10 ---- //---- label10 ----
@@ -488,12 +488,12 @@ public class FlatComponentStateTest
//---- button1 ---- //---- button1 ----
button1.setText("text"); button1.setText("text");
button1.putClientProperty("JComponent.minimumWidth", 0); button1.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(button1, "cell 1 6"); add(button1, "cell 1 6");
//---- testDefaultButton1 ---- //---- testDefaultButton1 ----
testDefaultButton1.setText("text"); testDefaultButton1.setText("text");
testDefaultButton1.putClientProperty("JComponent.minimumWidth", 0); testDefaultButton1.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
add(testDefaultButton1, "cell 2 6"); add(testDefaultButton1, "cell 2 6");
//---- toggleButton1 ---- //---- toggleButton1 ----
@@ -506,19 +506,19 @@ public class FlatComponentStateTest
add(toggleButton2, "cell 6 6"); add(toggleButton2, "cell 6 6");
//---- button2 ---- //---- button2 ----
button2.putClientProperty("JComponent.minimumWidth", 0); button2.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 0);
button2.putClientProperty("JButton.buttonType", "help"); button2.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_HELP);
add(button2, "cell 9 6"); add(button2, "cell 9 6");
add(separator1, "cell 0 7 11 1"); add(separator1, "cell 0 7 11 1");
//---- label22 ---- //---- label22 ----
label22.setText("JCheckBox"); label22.setText("JCheckBox");
label22.putClientProperty("FlatLaf.styleClass", "h3"); label22.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(label22, "cell 1 8 2 1"); add(label22, "cell 1 8 2 1");
//---- label27 ---- //---- label27 ----
label27.setText("JRadioButton"); label27.setText("JRadioButton");
label27.putClientProperty("FlatLaf.styleClass", "h3"); label27.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(label27, "cell 5 8 2 1"); add(label27, "cell 5 8 2 1");
//---- label23 ---- //---- label23 ----

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.testing; package com.formdev.flatlaf.testing;
import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.ComponentOrientation; import java.awt.ComponentOrientation;
@@ -32,6 +33,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.function.Supplier;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelEvent;
@@ -492,53 +494,33 @@ public class FlatComponents2Test
list.setVisibleRowCount( visibleRowCount ); list.setVisibleRowCount( visibleRowCount );
} }
private void listAlternatingRowsChanged() {
UIManager.put( "List.alternateRowColor", listAlternatingRowsCheckBox.isSelected() ? Color.YELLOW : null );
FlatLaf.updateUILater();
}
private void treeRendererChanged() { private void treeRendererChanged() {
Object sel = treeRendererComboBox.getSelectedItem(); Object sel = treeRendererComboBox.getSelectedItem();
if( !(sel instanceof String) ) if( !(sel instanceof String) )
return; return;
JTree[] trees = { tree1, tree2, xTree1 }; Supplier<TreeCellRenderer> creator;
switch( (String) sel ) { switch( (String) sel ) {
case "default": default:
for( JTree tree : trees ) case "default": creator = DefaultTreeCellRenderer::new; break;
tree.setCellRenderer( new DefaultTreeCellRenderer() ); case "defaultSubclass": creator = TestDefaultTreeCellRenderer::new; break;
break; case "defaultWithIcons": creator = TestDefaultWithIconsTreeCellRenderer::new; break;
case "defaultWithIcon": creator = TestDefaultWithIconTreeCellRenderer::new; break;
case "defaultSubclass": case "label": creator = TestLabelTreeCellRenderer::new; break;
for( JTree tree : trees ) case "wide": creator = TestWideTreeCellRenderer::new; break;
tree.setCellRenderer( new TestDefaultTreeCellRenderer() ); case "swingxDefault": creator = DefaultTreeRenderer::new; break;
break; case "jideCheckBox": creator = () -> new CheckBoxTreeCellRenderer( new DefaultTreeCellRenderer() ); break;
case "jideStyled": creator = StyledTreeCellRenderer::new; break;
case "defaultWithIcons":
for( JTree tree : trees )
tree.setCellRenderer( new TestDefaultWithIconsTreeCellRenderer() );
break;
case "defaultWithIcon":
for( JTree tree : trees )
tree.setCellRenderer( new TestDefaultWithIconTreeCellRenderer() );
break;
case "label":
for( JTree tree : trees )
tree.setCellRenderer( new TestLabelTreeCellRenderer() );
break;
case "swingxDefault":
for( JTree tree : trees )
tree.setCellRenderer( new DefaultTreeRenderer() );
break;
case "jideCheckBox":
for( JTree tree : trees )
tree.setCellRenderer( new CheckBoxTreeCellRenderer( new DefaultTreeCellRenderer() ) );
break;
case "jideStyled":
for( JTree tree : trees )
tree.setCellRenderer( new StyledTreeCellRenderer() );
break;
} }
JTree[] trees = { tree1, tree2, xTree1 };
for( JTree tree : trees )
tree.setCellRenderer( creator.get() );
} }
private void treeWideSelectionChanged() { private void treeWideSelectionChanged() {
@@ -547,6 +529,17 @@ public class FlatComponents2Test
tree.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection ); tree.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection );
} }
private void treeWideCellRendererChanged() {
boolean wideCellRenderer = treeWideCellRendererCheckBox.isSelected();
for( JTree tree : allTrees )
tree.putClientProperty( FlatClientProperties.TREE_WIDE_CELL_RENDERER, wideCellRenderer );
}
private void treeAlternatingRowsChanged() {
UIManager.put( "Tree.alternateRowColor", treeAlternatingRowsCheckBox.isSelected() ? Color.cyan : null );
FlatLaf.updateUILater();
}
private void treePaintSelectionChanged() { private void treePaintSelectionChanged() {
boolean paintSelection = treePaintSelectionCheckBox.isSelected(); boolean paintSelection = treePaintSelectionCheckBox.isSelected();
for( JTree tree : allTrees ) for( JTree tree : allTrees )
@@ -687,11 +680,14 @@ public class FlatComponents2Test
listLayoutOrientationField = new JComboBox<>(); listLayoutOrientationField = new JComboBox<>();
JLabel listVisibleRowCountLabel = new JLabel(); JLabel listVisibleRowCountLabel = new JLabel();
listVisibleRowCountSpinner = new JSpinner(); listVisibleRowCountSpinner = new JSpinner();
listAlternatingRowsCheckBox = new JCheckBox();
treeOptionsPanel = new JPanel(); treeOptionsPanel = new JPanel();
JLabel treeRendererLabel = new JLabel(); JLabel treeRendererLabel = new JLabel();
treeRendererComboBox = new JComboBox<>(); treeRendererComboBox = new JComboBox<>();
treeWideSelectionCheckBox = new JCheckBox(); treeWideSelectionCheckBox = new JCheckBox();
treeWideCellRendererCheckBox = new JCheckBox();
treePaintSelectionCheckBox = new JCheckBox(); treePaintSelectionCheckBox = new JCheckBox();
treeAlternatingRowsCheckBox = new JCheckBox();
treePaintLinesCheckBox = new JCheckBox(); treePaintLinesCheckBox = new JCheckBox();
treeRedLinesCheckBox = new JCheckBox(); treeRedLinesCheckBox = new JCheckBox();
treeEditableCheckBox = new JCheckBox(); treeEditableCheckBox = new JCheckBox();
@@ -753,7 +749,7 @@ public class FlatComponents2Test
// rows // rows
"[]" + "[]" +
"[grow]" + "[grow]" +
"[]" + "[]0" +
"[]")); "[]"));
//---- listLabel ---- //---- listLabel ----
@@ -796,7 +792,7 @@ public class FlatComponents2Test
// rows // rows
"[]" + "[]" +
"[grow]" + "[grow]" +
"[]" + "[]0" +
"[]")); "[]"));
//---- tableLabel ---- //---- tableLabel ----
@@ -833,7 +829,7 @@ public class FlatComponents2Test
// rows // rows
"[]" + "[]" +
"[grow]" + "[grow]" +
"[]" + "[]0" +
"[]")); "[]"));
//---- treeLabel ---- //---- treeLabel ----
@@ -1022,6 +1018,7 @@ public class FlatComponents2Test
// rows // rows
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]")); "[]"));
//---- listRendererLabel ---- //---- listRendererLabel ----
@@ -1059,6 +1056,11 @@ public class FlatComponents2Test
listVisibleRowCountSpinner.setModel(new SpinnerNumberModel(8, 0, null, 1)); listVisibleRowCountSpinner.setModel(new SpinnerNumberModel(8, 0, null, 1));
listVisibleRowCountSpinner.addChangeListener(e -> listVisibleRowCountChanged()); listVisibleRowCountSpinner.addChangeListener(e -> listVisibleRowCountChanged());
listOptionsPanel.add(listVisibleRowCountSpinner, "cell 1 2"); listOptionsPanel.add(listVisibleRowCountSpinner, "cell 1 2");
//---- listAlternatingRowsCheckBox ----
listAlternatingRowsCheckBox.setText("alternating rows");
listAlternatingRowsCheckBox.addActionListener(e -> listAlternatingRowsChanged());
listOptionsPanel.add(listAlternatingRowsCheckBox, "cell 0 3 2 1,alignx left,growx 0");
} }
add(listOptionsPanel, "cell 0 4 4 1"); add(listOptionsPanel, "cell 0 4 4 1");
@@ -1088,6 +1090,7 @@ public class FlatComponents2Test
"defaultWithIcons", "defaultWithIcons",
"defaultWithIcon", "defaultWithIcon",
"label", "label",
"wide",
"swingxDefault", "swingxDefault",
"jideCheckBox", "jideCheckBox",
"jideStyled" "jideStyled"
@@ -1100,12 +1103,22 @@ public class FlatComponents2Test
treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged()); treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged());
treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 1"); treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 1");
//---- treeWideCellRendererCheckBox ----
treeWideCellRendererCheckBox.setText("wide cell renderer");
treeWideCellRendererCheckBox.addActionListener(e -> treeWideCellRendererChanged());
treeOptionsPanel.add(treeWideCellRendererCheckBox, "cell 0 1");
//---- treePaintSelectionCheckBox ---- //---- treePaintSelectionCheckBox ----
treePaintSelectionCheckBox.setText("paint selection"); treePaintSelectionCheckBox.setText("paint selection");
treePaintSelectionCheckBox.setSelected(true); treePaintSelectionCheckBox.setSelected(true);
treePaintSelectionCheckBox.addActionListener(e -> treePaintSelectionChanged()); treePaintSelectionCheckBox.addActionListener(e -> treePaintSelectionChanged());
treeOptionsPanel.add(treePaintSelectionCheckBox, "cell 0 2"); treeOptionsPanel.add(treePaintSelectionCheckBox, "cell 0 2");
//---- treeAlternatingRowsCheckBox ----
treeAlternatingRowsCheckBox.setText("alternating rows");
treeAlternatingRowsCheckBox.addActionListener(e -> treeAlternatingRowsChanged());
treeOptionsPanel.add(treeAlternatingRowsCheckBox, "cell 0 2");
//---- treePaintLinesCheckBox ---- //---- treePaintLinesCheckBox ----
treePaintLinesCheckBox.setText("paint lines"); treePaintLinesCheckBox.setText("paint lines");
treePaintLinesCheckBox.addActionListener(e -> treePaintLinesChanged()); treePaintLinesCheckBox.addActionListener(e -> treePaintLinesChanged());
@@ -1263,10 +1276,13 @@ public class FlatComponents2Test
private JComboBox<String> listRendererComboBox; private JComboBox<String> listRendererComboBox;
private JComboBox<String> listLayoutOrientationField; private JComboBox<String> listLayoutOrientationField;
private JSpinner listVisibleRowCountSpinner; private JSpinner listVisibleRowCountSpinner;
private JCheckBox listAlternatingRowsCheckBox;
private JPanel treeOptionsPanel; private JPanel treeOptionsPanel;
private JComboBox<String> treeRendererComboBox; private JComboBox<String> treeRendererComboBox;
private JCheckBox treeWideSelectionCheckBox; private JCheckBox treeWideSelectionCheckBox;
private JCheckBox treeWideCellRendererCheckBox;
private JCheckBox treePaintSelectionCheckBox; private JCheckBox treePaintSelectionCheckBox;
private JCheckBox treeAlternatingRowsCheckBox;
private JCheckBox treePaintLinesCheckBox; private JCheckBox treePaintLinesCheckBox;
private JCheckBox treeRedLinesCheckBox; private JCheckBox treeRedLinesCheckBox;
private JCheckBox treeEditableCheckBox; private JCheckBox treeEditableCheckBox;
@@ -1372,7 +1388,7 @@ public class FlatComponents2Test
@Override @Override
public String getElementAt( int index ) { public String getElementAt( int index ) {
return (index < 20) return (index < 20)
? "item " + (index + 1) ? "item " + (index + 1) + ((index + 1) % 5 == 0 ? " ####" : "")
: "item " + (index + 1) + " " + randomRowString( index ); : "item " + (index + 1) + " " + randomRowString( index );
} }
} }
@@ -1794,6 +1810,32 @@ public class FlatComponents2Test
} }
} }
//---- class TestLabelTreeCellRenderer ------------------------------------
private static class TestWideTreeCellRenderer
extends JPanel
implements TreeCellRenderer
{
private final JLabel label = new JLabel();
private final JLabel icon = new JLabel( UIManager.getIcon( "FileView.floppyDriveIcon" ) );
TestWideTreeCellRenderer() {
super( new BorderLayout() );
setOpaque( false );
add( label, BorderLayout.CENTER );
add( icon, BorderLayout.LINE_END );
setBorder( new LineBorder( Color.red ) );
}
@Override
public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus )
{
label.setText( String.valueOf( value ) );
return this;
}
}
//---- class TestComboBoxTableCellRenderer -------------------------------- //---- class TestComboBoxTableCellRenderer --------------------------------
private static class TestComboBoxTableCellRenderer private static class TestComboBoxTableCellRenderer

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.2.2.0.9999" Java: "21.0.1" encoding: "UTF-8" JFDML JFormDesigner: "8.3" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -33,7 +33,7 @@ new FormModel {
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]" "$columnConstraints": "[fill]"
"$rowConstraints": "[][grow][][]" "$rowConstraints": "[][grow][]0[]"
"$layoutConstraints": "ltr,insets 0,hidemode 3" "$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) { } ) {
name: "panel1" name: "panel1"
@@ -95,7 +95,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3" "$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]" "$columnConstraints": "[fill]"
"$rowConstraints": "[][grow][][]" "$rowConstraints": "[][grow][]0[]"
} ) { } ) {
name: "panel3" name: "panel3"
"$client.FlatLaf.internal.testing.ignore": true "$client.FlatLaf.internal.testing.ignore": true
@@ -146,7 +146,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3" "$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[fill]" "$columnConstraints": "[fill]"
"$rowConstraints": "[][grow][][]" "$rowConstraints": "[][grow][]0[]"
} ) { } ) {
name: "panel2" name: "panel2"
"$client.FlatLaf.internal.testing.ignore": true "$client.FlatLaf.internal.testing.ignore": true
@@ -385,7 +385,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 8,hidemode 3" "$layoutConstraints": "insets 8,hidemode 3"
"$columnConstraints": "[fill][fill]" "$columnConstraints": "[fill][fill]"
"$rowConstraints": "[][][]" "$rowConstraints": "[][][][]"
} ) { } ) {
name: "listOptionsPanel" name: "listOptionsPanel"
"border": new javax.swing.border.TitledBorder( "JList Control" ) "border": new javax.swing.border.TitledBorder( "JList Control" )
@@ -455,6 +455,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2" "value": "cell 1 2"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "listAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 2 1,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 4 1" "value": "cell 0 4 4 1"
} ) } )
@@ -484,6 +494,7 @@ new FormModel {
addElement( "defaultWithIcons" ) addElement( "defaultWithIcons" )
addElement( "defaultWithIcon" ) addElement( "defaultWithIcon" )
addElement( "label" ) addElement( "label" )
addElement( "wide" )
addElement( "swingxDefault" ) addElement( "swingxDefault" )
addElement( "jideCheckBox" ) addElement( "jideCheckBox" )
addElement( "jideStyled" ) addElement( "jideStyled" )
@@ -505,6 +516,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1" "value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeWideCellRendererCheckBox"
"text": "wide cell renderer"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeWideCellRendererChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treePaintSelectionCheckBox" name: "treePaintSelectionCheckBox"
"text": "paint selection" "text": "paint selection"
@@ -516,6 +537,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2" "value": "cell 0 2"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treeAlternatingRowsCheckBox"
"text": "alternating rows"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeAlternatingRowsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "treePaintLinesCheckBox" name: "treePaintLinesCheckBox"
"text": "paint lines" "text": "paint lines"

View File

@@ -20,6 +20,7 @@ import java.awt.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.extras.components.*; import com.formdev.flatlaf.extras.components.*;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType; import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
@@ -59,6 +60,11 @@ public class FlatComponentsTest
}; };
for( JSlider slider : allSliders ) for( JSlider slider : allSliders )
slider.addChangeListener( sliderChanged ); slider.addChangeListener( sliderChanged );
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) && hideArrowButtonCheckBox.isSelected() )
SwingUtilities.invokeLater( () -> hideArrowButton() );
} );
} }
private void changeProgress() { private void changeProgress() {
@@ -127,6 +133,48 @@ public class FlatComponentsTest
} }
} }
private void hideArrowButton() {
boolean hideArrowButton = hideArrowButtonCheckBox.isSelected();
for( Component c : getComponents() ) {
if( c instanceof JComboBox ) {
Component b = ((JComboBox<?>)c).getComponent( 0 );
if( b instanceof AbstractButton )
b.setVisible( !hideArrowButton );
}
}
}
private void transparentBackground() {
EventQueue.invokeLater( () -> {
boolean transparent = transparentBackgroundCheckBox.isSelected();
Color transparentColor = new Color( 0, true );
ColorUIResource restoreColor = new ColorUIResource( Color.white );
FlatTestFrame.updateComponentsRecur( this, (c, type) -> {
if( c instanceof JComboBox ) {
((JComboBox<?>)c).putClientProperty( FlatClientProperties.STYLE,
transparent ? "background: #0000; buttonBackground: #0000; buttonEditableBackground: #0000" : null );
} else if( c instanceof JSpinner ) {
((JSpinner)c).putClientProperty( FlatClientProperties.STYLE,
transparent ? "background: #0000; buttonBackground: #0000" : null );
} else if( c instanceof JComponent )
c.setBackground( transparent ? transparentColor : restoreColor );
else
return;
// if background color is transparent it is also required to make the component non-opaque
// DO NOT USE LookAndFeel.installProperty() in real-world applications
// instead use c.setOpaque( false )
if( transparent )
LookAndFeel.installProperty( (JComponent) c, "opaque", false );
} );
if( !transparent )
SwingUtilities.updateComponentTreeUI( this );
} );
}
private void roundRectChanged() { private void roundRectChanged() {
Boolean roundRect = roundRectCheckBox.isSelected() ? true : null; Boolean roundRect = roundRectCheckBox.isSelected() ? true : null;
@@ -380,6 +428,8 @@ public class FlatComponentsTest
magentaOutlineRadioButton = new JRadioButton(); magentaOutlineRadioButton = new JRadioButton();
magentaCyanOutlineRadioButton = new JRadioButton(); magentaCyanOutlineRadioButton = new JRadioButton();
focusPaintedCheckBox = new JCheckBox(); focusPaintedCheckBox = new JCheckBox();
hideArrowButtonCheckBox = new JCheckBox();
transparentBackgroundCheckBox = new JCheckBox();
JLabel scrollBarLabel = new JLabel(); JLabel scrollBarLabel = new JLabel();
JScrollBar scrollBar1 = new JScrollBar(); JScrollBar scrollBar1 = new JScrollBar();
JScrollBar scrollBar4 = new JScrollBar(); JScrollBar scrollBar4 = new JScrollBar();
@@ -1234,9 +1284,11 @@ public class FlatComponentsTest
"[]" + "[]" +
"[]", "[]",
// rows // rows
"[]" + "[]0" +
"[]" + "[]0" +
"[]" + "[]0" +
"[]0" +
"[]0" +
"[]")); "[]"));
//---- buttonTypeComboBox ---- //---- buttonTypeComboBox ----
@@ -1290,13 +1342,23 @@ public class FlatComponentsTest
magentaCyanOutlineRadioButton.addActionListener(e -> outlineChanged()); magentaCyanOutlineRadioButton.addActionListener(e -> outlineChanged());
panel4.add(magentaCyanOutlineRadioButton); panel4.add(magentaCyanOutlineRadioButton);
} }
panel5.add(panel4, "cell 0 2 1 2"); panel5.add(panel4, "cell 0 2 1 4");
//---- focusPaintedCheckBox ---- //---- focusPaintedCheckBox ----
focusPaintedCheckBox.setText("focusPainted"); focusPaintedCheckBox.setText("focusPainted");
focusPaintedCheckBox.setSelected(true); focusPaintedCheckBox.setSelected(true);
focusPaintedCheckBox.addActionListener(e -> focusPaintedChanged()); focusPaintedCheckBox.addActionListener(e -> focusPaintedChanged());
panel5.add(focusPaintedCheckBox, "cell 1 2"); panel5.add(focusPaintedCheckBox, "cell 1 2");
//---- hideArrowButtonCheckBox ----
hideArrowButtonCheckBox.setText("hide arrow button");
hideArrowButtonCheckBox.addActionListener(e -> hideArrowButton());
panel5.add(hideArrowButtonCheckBox, "cell 1 3");
//---- transparentBackgroundCheckBox ----
transparentBackgroundCheckBox.setText("transparent background");
transparentBackgroundCheckBox.addActionListener(e -> transparentBackground());
panel5.add(transparentBackgroundCheckBox, "cell 1 4");
} }
add(panel5, "cell 5 13 2 10,grow"); add(panel5, "cell 5 13 2 10,grow");
@@ -1703,6 +1765,8 @@ public class FlatComponentsTest
private JRadioButton magentaOutlineRadioButton; private JRadioButton magentaOutlineRadioButton;
private JRadioButton magentaCyanOutlineRadioButton; private JRadioButton magentaCyanOutlineRadioButton;
private JCheckBox focusPaintedCheckBox; private JCheckBox focusPaintedCheckBox;
private JCheckBox hideArrowButtonCheckBox;
private JCheckBox transparentBackgroundCheckBox;
private JSlider slider1; private JSlider slider1;
private JSlider slider6; private JSlider slider6;
private JCheckBox sliderPaintTrackCheckBox; private JCheckBox sliderPaintTrackCheckBox;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.5.0.404" Java: "17.0.2" encoding: "UTF-8" JFDML JFormDesigner: "8.3" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -993,7 +993,7 @@ new FormModel {
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[][]" "$columnConstraints": "[][]"
"$rowConstraints": "[][][][]" "$rowConstraints": "[]0[]0[]0[]0[]0[]"
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
} ) { } ) {
name: "panel5" name: "panel5"
@@ -1092,7 +1092,7 @@ new FormModel {
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "outlineChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "outlineChanged", false ) )
} ) } )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2 1 2" "value": "cell 0 2 1 4"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "focusPaintedCheckBox" name: "focusPaintedCheckBox"
@@ -1105,6 +1105,26 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2" "value": "cell 1 2"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hideArrowButtonCheckBox"
"text": "hide arrow button"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideArrowButton", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "transparentBackgroundCheckBox"
"text": "transparent background"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "transparentBackground", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 13 2 10,grow" "value": "cell 5 13 2 10,grow"
} ) } )

View File

@@ -21,6 +21,7 @@ import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.plaf.basic.BasicComboBoxEditor; import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.plaf.basic.BasicComboBoxRenderer; import javax.swing.plaf.basic.BasicComboBoxRenderer;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon; import com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
@@ -342,22 +343,22 @@ public class FlatCustomBordersTest
//---- button5 ---- //---- button5 ----
button5.setText("text"); button5.setText("text");
button5.putClientProperty("JButton.buttonType", "roundRect"); button5.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_ROUND_RECT);
add(button5, "cell 1 2"); add(button5, "cell 1 2");
//---- button6 ---- //---- button6 ----
button6.setText("text"); button6.setText("text");
button6.putClientProperty("JButton.buttonType", "roundRect"); button6.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_ROUND_RECT);
add(button6, "cell 2 2"); add(button6, "cell 2 2");
//---- button7 ---- //---- button7 ----
button7.setText("text"); button7.setText("text");
button7.putClientProperty("JButton.buttonType", "roundRect"); button7.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_ROUND_RECT);
add(button7, "cell 3 2"); add(button7, "cell 3 2");
//---- button8 ---- //---- button8 ----
button8.setText("text"); button8.setText("text");
button8.putClientProperty("JButton.buttonType", "roundRect"); button8.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_ROUND_RECT);
add(button8, "cell 4 2"); add(button8, "cell 4 2");
//---- label5 ---- //---- label5 ----
@@ -372,31 +373,31 @@ public class FlatCustomBordersTest
add(comboBox27, "cell 7 3"); add(comboBox27, "cell 7 3");
//---- comboBox5 ---- //---- comboBox5 ----
comboBox5.putClientProperty("JComponent.roundRect", true); comboBox5.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox5, "cell 1 4"); add(comboBox5, "cell 1 4");
//---- comboBox6 ---- //---- comboBox6 ----
comboBox6.putClientProperty("JComponent.roundRect", true); comboBox6.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox6, "cell 2 4"); add(comboBox6, "cell 2 4");
//---- comboBox7 ---- //---- comboBox7 ----
comboBox7.putClientProperty("JComponent.roundRect", true); comboBox7.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox7, "cell 3 4"); add(comboBox7, "cell 3 4");
//---- comboBox8 ---- //---- comboBox8 ----
comboBox8.putClientProperty("JComponent.roundRect", true); comboBox8.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox8, "cell 4 4"); add(comboBox8, "cell 4 4");
//---- comboBox24 ---- //---- comboBox24 ----
comboBox24.putClientProperty("JComponent.roundRect", true); comboBox24.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox24, "cell 5 4"); add(comboBox24, "cell 5 4");
//---- comboBox26 ---- //---- comboBox26 ----
comboBox26.putClientProperty("JComponent.roundRect", true); comboBox26.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox26, "cell 6 4"); add(comboBox26, "cell 6 4");
//---- comboBox28 ---- //---- comboBox28 ----
comboBox28.putClientProperty("JComponent.roundRect", true); comboBox28.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(comboBox28, "cell 7 4"); add(comboBox28, "cell 7 4");
//---- comboBox9 ---- //---- comboBox9 ----
@@ -428,37 +429,37 @@ public class FlatCustomBordersTest
add(comboBox21, "cell 7 5"); add(comboBox21, "cell 7 5");
//---- comboBox13 ---- //---- comboBox13 ----
comboBox13.putClientProperty("JComponent.roundRect", true); comboBox13.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox13.setEditable(true); comboBox13.setEditable(true);
add(comboBox13, "cell 1 6"); add(comboBox13, "cell 1 6");
//---- comboBox14 ---- //---- comboBox14 ----
comboBox14.putClientProperty("JComponent.roundRect", true); comboBox14.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox14.setEditable(true); comboBox14.setEditable(true);
add(comboBox14, "cell 2 6"); add(comboBox14, "cell 2 6");
//---- comboBox15 ---- //---- comboBox15 ----
comboBox15.putClientProperty("JComponent.roundRect", true); comboBox15.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox15.setEditable(true); comboBox15.setEditable(true);
add(comboBox15, "cell 3 6"); add(comboBox15, "cell 3 6");
//---- comboBox16 ---- //---- comboBox16 ----
comboBox16.putClientProperty("JComponent.roundRect", true); comboBox16.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox16.setEditable(true); comboBox16.setEditable(true);
add(comboBox16, "cell 4 6"); add(comboBox16, "cell 4 6");
//---- comboBox18 ---- //---- comboBox18 ----
comboBox18.putClientProperty("JComponent.roundRect", true); comboBox18.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox18.setEditable(true); comboBox18.setEditable(true);
add(comboBox18, "cell 5 6"); add(comboBox18, "cell 5 6");
//---- comboBox20 ---- //---- comboBox20 ----
comboBox20.putClientProperty("JComponent.roundRect", true); comboBox20.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox20.setEditable(true); comboBox20.setEditable(true);
add(comboBox20, "cell 6 6"); add(comboBox20, "cell 6 6");
//---- comboBox22 ---- //---- comboBox22 ----
comboBox22.putClientProperty("JComponent.roundRect", true); comboBox22.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
comboBox22.setEditable(true); comboBox22.setEditable(true);
add(comboBox22, "cell 7 6"); add(comboBox22, "cell 7 6");
@@ -471,19 +472,19 @@ public class FlatCustomBordersTest
add(spinner4, "cell 4 7"); add(spinner4, "cell 4 7");
//---- spinner5 ---- //---- spinner5 ----
spinner5.putClientProperty("JComponent.roundRect", true); spinner5.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(spinner5, "cell 1 8"); add(spinner5, "cell 1 8");
//---- spinner6 ---- //---- spinner6 ----
spinner6.putClientProperty("JComponent.roundRect", true); spinner6.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(spinner6, "cell 2 8"); add(spinner6, "cell 2 8");
//---- spinner7 ---- //---- spinner7 ----
spinner7.putClientProperty("JComponent.roundRect", true); spinner7.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(spinner7, "cell 3 8"); add(spinner7, "cell 3 8");
//---- spinner8 ---- //---- spinner8 ----
spinner8.putClientProperty("JComponent.roundRect", true); spinner8.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(spinner8, "cell 4 8"); add(spinner8, "cell 4 8");
//---- textFieldLabel ---- //---- textFieldLabel ----
@@ -492,11 +493,11 @@ public class FlatCustomBordersTest
//---- textField1 ---- //---- textField1 ----
textField1.setText("text"); textField1.setText("text");
textField1.putClientProperty("JComponent.roundRect", false); textField1.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, false);
add(textField1, "cell 1 9,growx"); add(textField1, "cell 1 9,growx");
//---- textField2 ---- //---- textField2 ----
textField2.putClientProperty("JComponent.roundRect", false); textField2.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, false);
textField2.setText("text"); textField2.setText("text");
add(textField2, "cell 2 9"); add(textField2, "cell 2 9");
@@ -505,27 +506,27 @@ public class FlatCustomBordersTest
add(textField3, "cell 3 9"); add(textField3, "cell 3 9");
//---- textField4 ---- //---- textField4 ----
textField4.putClientProperty("JComponent.roundRect", false); textField4.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, false);
textField4.setText("text"); textField4.setText("text");
add(textField4, "cell 4 9"); add(textField4, "cell 4 9");
//---- textField5 ---- //---- textField5 ----
textField5.setText("text"); textField5.setText("text");
textField5.putClientProperty("JComponent.roundRect", true); textField5.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(textField5, "cell 1 10,growx"); add(textField5, "cell 1 10,growx");
//---- textField6 ---- //---- textField6 ----
textField6.putClientProperty("JComponent.roundRect", true); textField6.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
textField6.setText("text"); textField6.setText("text");
add(textField6, "cell 2 10"); add(textField6, "cell 2 10");
//---- textField7 ---- //---- textField7 ----
textField7.setText("text"); textField7.setText("text");
textField7.putClientProperty("JComponent.roundRect", true); textField7.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
add(textField7, "cell 3 10"); add(textField7, "cell 3 10");
//---- textField8 ---- //---- textField8 ----
textField8.putClientProperty("JComponent.roundRect", true); textField8.putClientProperty(FlatClientProperties.COMPONENT_ROUND_RECT, true);
textField8.setText("text"); textField8.setText("text");
add(textField8, "cell 4 10"); add(textField8, "cell 4 10");

View File

@@ -22,6 +22,7 @@ import java.awt.Font;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import javax.swing.*; import javax.swing.*;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.fonts.inter.FlatInterFont; import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont; import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont; import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
@@ -132,7 +133,7 @@ public class FlatFontsTest
//---- previewFamilyNameLabel ---- //---- previewFamilyNameLabel ----
previewFamilyNameLabel.setText("name"); previewFamilyNameLabel.setText("name");
previewFamilyNameLabel.putClientProperty("FlatLaf.styleClass", "h1"); previewFamilyNameLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(previewFamilyNameLabel, "cell 1 1"); add(previewFamilyNameLabel, "cell 1 1");
//======== familiesScrollPane ======== //======== familiesScrollPane ========

View File

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

View File

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

View File

@@ -21,6 +21,10 @@ import java.awt.event.MouseEvent;
import java.util.Random; import java.util.Random;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.util.Animator; import com.formdev.flatlaf.util.Animator;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
@@ -43,6 +47,8 @@ public class FlatPopupTest
FlatPopupTest() { FlatPopupTest() {
initComponents(); initComponents();
addPopupMenuListener( popupMenu1, "popupMenu1" );
addPopupMenuListener( popupMenu2, "popupMenu2" );
} }
private void showPopupMenu() { private void showPopupMenu() {
@@ -114,6 +120,46 @@ public class FlatPopupTest
} }
} }
private void showDirectPopup() {
DirectPopupContent content = new DirectPopupContent();
content.putClientProperty( FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, true );
Point pt = showDirectPopupButton.getLocationOnScreen();
System.setProperty( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, "false" );
UIManager.put( "Popup.dropShadowColor", Color.red );
UIManager.put( "Popup.dropShadowInsets", new Insets( 5, 5, 5, 5 ) );
UIManager.put( "Popup.dropShadowOpacity", 1f );
Popup popup = PopupFactory.getSharedInstance().getPopup( showDirectPopupButton,
content, pt.x, pt.y + showDirectPopupButton.getHeight() + 10 );
content.popup = popup;
popup.show();
System.clearProperty( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER );
UIManager.put( "Popup.dropShadowColor", null );
UIManager.put( "Popup.dropShadowInsets", null );
UIManager.put( "Popup.dropShadowOpacity", null );
}
private void addPopupMenuListener( JPopupMenu popupMenu, String name ) {
popupMenu.addPopupMenuListener( new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {
System.out.println( "popupMenuWillBecomeVisible " + name );
}
@Override
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
System.out.println( "popupMenuWillBecomeInvisible " + name );
}
@Override
public void popupMenuCanceled( PopupMenuEvent e ) {
System.out.println( "popupMenuCanceled " + name );
}
} );
}
@Override @Override
public void updateUI() { public void updateUI() {
super.updateUI(); super.updateUI();
@@ -128,15 +174,12 @@ public class FlatPopupTest
} }
} }
private void countChanged() {
// TODO add your code here
}
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel(); label1 = new JLabel();
label2 = new JLabel(); label2 = new JLabel();
showPopupMenuButton = new JButton(); showPopupMenuButton = new JButton();
showDirectPopupButton = new JButton();
showLargePopupMenuButton = new JButton(); showLargePopupMenuButton = new JButton();
showPopupButton = new JButton(); showPopupButton = new JButton();
hidePopupButton = new JButton(); hidePopupButton = new JButton();
@@ -209,6 +252,11 @@ public class FlatPopupTest
showPopupMenuButton.addActionListener(e -> showPopupMenu()); showPopupMenuButton.addActionListener(e -> showPopupMenu());
add(showPopupMenuButton, "cell 0 2"); add(showPopupMenuButton, "cell 0 2");
//---- showDirectPopupButton ----
showDirectPopupButton.setText("show direct move/resize popup");
showDirectPopupButton.addActionListener(e -> showDirectPopup());
add(showDirectPopupButton, "cell 2 2 2 1");
//---- showLargePopupMenuButton ---- //---- showLargePopupMenuButton ----
showLargePopupMenuButton.setText("show heavy-weight JPopupMenu"); showLargePopupMenuButton.setText("show heavy-weight JPopupMenu");
showLargePopupMenuButton.addActionListener(e -> showLargePopupMenu()); showLargePopupMenuButton.addActionListener(e -> showLargePopupMenu());
@@ -240,7 +288,6 @@ public class FlatPopupTest
//---- countField ---- //---- countField ----
countField.setModel(new SpinnerNumberModel(1, 1, null, 1)); countField.setModel(new SpinnerNumberModel(1, 1, null, 1));
countField.addChangeListener(e -> countChanged());
add(countField, "cell 5 4"); add(countField, "cell 5 4");
//---- label4 ---- //---- label4 ----
@@ -366,6 +413,7 @@ public class FlatPopupTest
private JLabel label1; private JLabel label1;
private JLabel label2; private JLabel label2;
private JButton showPopupMenuButton; private JButton showPopupMenuButton;
private JButton showDirectPopupButton;
private JButton showLargePopupMenuButton; private JButton showLargePopupMenuButton;
private JButton showPopupButton; private JButton showPopupButton;
private JButton hidePopupButton; private JButton hidePopupButton;
@@ -444,4 +492,69 @@ public class FlatPopupTest
private JLabel label6; private JLabel label6;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on // JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
} }
//---- class MyPopupContent -----------------------------------------------
private static class DirectPopupContent
extends JPanel
{
Popup popup;
DirectPopupContent() {
initComponents();
}
private void resizePopup() {
Window popupWindow = SwingUtilities.windowForComponent( this );
popupWindow.setSize( popupWindow.getWidth() + 20, popupWindow.getHeight() + 50 );
}
private void movePopup() {
Window popupWindow = SwingUtilities.windowForComponent( this );
popupWindow.setLocation( popupWindow.getX() + 20, popupWindow.getY() + 50 );
}
private void hidePopup() {
popup.hide();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents @formatter:off
resizeButton = new JButton();
moveButton = new JButton();
hideButton = new JButton();
//======== this ========
setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]" +
"[fill]" +
"[fill]",
// rows
"[]"));
//---- resizeButton ----
resizeButton.setText("Resize");
resizeButton.addActionListener(e -> resizePopup());
add(resizeButton, "cell 0 0");
//---- moveButton ----
moveButton.setText("Move");
moveButton.addActionListener(e -> movePopup());
add(moveButton, "cell 1 0");
//---- hideButton ----
hideButton.setText("Hide");
hideButton.addActionListener(e -> hidePopup());
add(hideButton, "cell 2 0");
// JFormDesigner - End of component initialization //GEN-END:initComponents @formatter:on
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @formatter:off
private JButton resizeButton;
private JButton moveButton;
private JButton hideButton;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
}
} }

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.2.3.0.386" Java: "21" encoding: "UTF-8" JFDML JFormDesigner: "8.3" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -30,6 +30,13 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2" "value": "cell 0 2"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showDirectPopupButton"
"text": "show direct move/resize popup"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showDirectPopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 2 2 1"
} )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "showLargePopupMenuButton" name: "showLargePopupMenuButton"
"text": "show heavy-weight JPopupMenu" "text": "show heavy-weight JPopupMenu"
@@ -77,7 +84,6 @@ new FormModel {
minimum: 1 minimum: 1
value: 1 value: 1
} }
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "countChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 4" "value": "cell 5 4"
} ) } )
@@ -215,5 +221,39 @@ new FormModel {
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 5, 505 ) "location": new java.awt.Point( 5, 505 )
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill][fill][fill]"
"$rowConstraints": "[]"
} ) {
name: "panel1"
auxiliary() {
"JavaCodeGenerator.className": "DirectPopupContent"
}
add( new FormComponent( "javax.swing.JButton" ) {
name: "resizeButton"
"text": "Resize"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "resizePopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "moveButton"
"text": "Move"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "movePopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "hideButton"
"text": "Hide"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hidePopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 180, 395 )
"size": new java.awt.Dimension( 270, 100 )
} )
} }
} }

View File

@@ -37,6 +37,7 @@ import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel; import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf; import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf; import com.formdev.flatlaf.FlatIntelliJLaf;
@@ -806,7 +807,7 @@ public class FlatTestFrame
buttonBar.add(scaleFactorComboBox, "cell 1 0"); buttonBar.add(scaleFactorComboBox, "cell 1 0");
//---- fontSizeSpinner ---- //---- fontSizeSpinner ----
fontSizeSpinner.putClientProperty("JComponent.minimumWidth", 50); fontSizeSpinner.putClientProperty(FlatClientProperties.MINIMUM_WIDTH, 50);
fontSizeSpinner.setModel(new SpinnerNumberModel(0, 0, null, 1)); fontSizeSpinner.setModel(new SpinnerNumberModel(0, 0, null, 1));
fontSizeSpinner.addChangeListener(e -> fontSizeChanged()); fontSizeSpinner.addChangeListener(e -> fontSizeChanged());
buttonBar.add(fontSizeSpinner, "cell 2 0"); buttonBar.add(fontSizeSpinner, "cell 2 0");

View File

@@ -316,13 +316,13 @@ public class FlatTextComponentsTest
//---- textField1 ---- //---- textField1 ----
textField1.setText("editable"); textField1.setText("editable");
textField1.setComponentPopupMenu(popupMenu1); textField1.setComponentPopupMenu(popupMenu1);
textField1.putClientProperty("JTextField.placeholderText", "place"); textField1.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(textField1, "cell 1 0,growx"); add(textField1, "cell 1 0,growx");
//---- textField3 ---- //---- textField3 ----
textField3.setText("longer text for testing horizontal scrolling"); textField3.setText("longer text for testing horizontal scrolling");
textField3.setComponentPopupMenu(popupMenu1); textField3.setComponentPopupMenu(popupMenu1);
textField3.putClientProperty("JTextField.placeholderText", "place"); textField3.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(textField3, "cell 2 0,growx"); add(textField3, "cell 2 0,growx");
//---- textField2 ---- //---- textField2 ----
@@ -330,7 +330,7 @@ public class FlatTextComponentsTest
textField2.setSelectionStart(1); textField2.setSelectionStart(1);
textField2.setSelectionEnd(4); textField2.setSelectionEnd(4);
textField2.setComponentPopupMenu(popupMenu1); textField2.setComponentPopupMenu(popupMenu1);
textField2.putClientProperty("JTextField.placeholderText", "place"); textField2.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(textField2, "cell 3 0"); add(textField2, "cell 3 0");
//---- formattedTextFieldLabel ---- //---- formattedTextFieldLabel ----
@@ -342,13 +342,13 @@ public class FlatTextComponentsTest
//---- formattedTextField1 ---- //---- formattedTextField1 ----
formattedTextField1.setText("editable"); formattedTextField1.setText("editable");
formattedTextField1.setComponentPopupMenu(popupMenu1); formattedTextField1.setComponentPopupMenu(popupMenu1);
formattedTextField1.putClientProperty("JTextField.placeholderText", "place"); formattedTextField1.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(formattedTextField1, "cell 1 1,growx"); add(formattedTextField1, "cell 1 1,growx");
//---- formattedTextField3 ---- //---- formattedTextField3 ----
formattedTextField3.setText("longer text for testing horizontal scrolling"); formattedTextField3.setText("longer text for testing horizontal scrolling");
formattedTextField3.setComponentPopupMenu(popupMenu1); formattedTextField3.setComponentPopupMenu(popupMenu1);
formattedTextField3.putClientProperty("JTextField.placeholderText", "place"); formattedTextField3.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(formattedTextField3, "cell 2 1,growx"); add(formattedTextField3, "cell 2 1,growx");
//======== panel1 ======== //======== panel1 ========
@@ -539,13 +539,13 @@ public class FlatTextComponentsTest
//---- passwordField1 ---- //---- passwordField1 ----
passwordField1.setText("editable"); passwordField1.setText("editable");
passwordField1.setComponentPopupMenu(popupMenu1); passwordField1.setComponentPopupMenu(popupMenu1);
passwordField1.putClientProperty("JTextField.placeholderText", "place"); passwordField1.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(passwordField1, "cell 1 2,growx"); add(passwordField1, "cell 1 2,growx");
//---- passwordField3 ---- //---- passwordField3 ----
passwordField3.setText("longer text for testing horizontal scrolling"); passwordField3.setText("longer text for testing horizontal scrolling");
passwordField3.setComponentPopupMenu(popupMenu1); passwordField3.setComponentPopupMenu(popupMenu1);
passwordField3.putClientProperty("JTextField.placeholderText", "place"); passwordField3.putClientProperty(FlatClientProperties.PLACEHOLDER_TEXT, "place");
add(passwordField3, "cell 2 2,growx"); add(passwordField3, "cell 2 2,growx");
//---- textAreaLabel ---- //---- textAreaLabel ----

View File

@@ -24,6 +24,7 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import javax.swing.*; import javax.swing.*;
import com.formdev.flatlaf.FlatClientProperties;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -205,57 +206,57 @@ public class FlatTypographyTest
//---- label54 ---- //---- label54 ----
label54.setText("<html>FlatLaf<br><small>Windows</small></html>"); label54.setText("<html>FlatLaf<br><small>Windows</small></html>");
label54.putClientProperty("FlatLaf.styleClass", "h1"); label54.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label54, "cell 0 0"); add(label54, "cell 0 0");
//---- label68 ---- //---- label68 ----
label68.setText("<html>JetBrains<br><small>Windows</small></html>"); label68.setText("<html>JetBrains<br><small>Windows</small></html>");
label68.putClientProperty("FlatLaf.styleClass", "h1"); label68.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label68, "cell 1 0"); add(label68, "cell 1 0");
//---- label69 ---- //---- label69 ----
label69.setText("<html>JetBrains<br><small>macOS</small></html>"); label69.setText("<html>JetBrains<br><small>macOS</small></html>");
label69.putClientProperty("FlatLaf.styleClass", "h1"); label69.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label69, "cell 2 0"); add(label69, "cell 2 0");
//---- label10 ---- //---- label10 ----
label10.setText("macOS"); label10.setText("macOS");
label10.putClientProperty("FlatLaf.styleClass", "h1"); label10.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label10, "cell 3 0"); add(label10, "cell 3 0");
//---- label11 ---- //---- label11 ----
label11.setText("Windows 10/11"); label11.setText("Windows 10/11");
label11.putClientProperty("FlatLaf.styleClass", "h1"); label11.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label11, "cell 4 0"); add(label11, "cell 4 0");
//---- label72 ---- //---- label72 ----
label72.setText("<html>GitHub<br>Primer</html>"); label72.setText("<html>GitHub<br>Primer</html>");
label72.putClientProperty("FlatLaf.styleClass", "h1"); label72.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label72, "cell 5 0"); add(label72, "cell 5 0");
//---- label28 ---- //---- label28 ----
label28.setText("Material"); label28.setText("Material");
label28.putClientProperty("FlatLaf.styleClass", "h1"); label28.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label28, "cell 6 0"); add(label28, "cell 6 0");
//---- label29 ---- //---- label29 ----
label29.setText("Material 3"); label29.setText("Material 3");
label29.putClientProperty("FlatLaf.styleClass", "h1"); label29.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label29, "cell 7 0"); add(label29, "cell 7 0");
//---- label1 ---- //---- label1 ----
label1.setText("SAP Fiori"); label1.setText("SAP Fiori");
label1.putClientProperty("FlatLaf.styleClass", "h1"); label1.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label1, "cell 8 0"); add(label1, "cell 8 0");
//---- label37 ---- //---- label37 ----
label37.setText("Atlassian"); label37.setText("Atlassian");
label37.putClientProperty("FlatLaf.styleClass", "h1"); label37.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label37, "cell 9 0"); add(label37, "cell 9 0");
//---- label46 ---- //---- label46 ----
label46.setText("Iris"); label46.setText("Iris");
label46.putClientProperty("FlatLaf.styleClass", "h1"); label46.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(label46, "cell 10 0"); add(label46, "cell 10 0");
//---- linkLabel9 ---- //---- linkLabel9 ----
@@ -1147,7 +1148,7 @@ public class FlatTypographyTest
//---- descLabel ---- //---- descLabel ----
descLabel.setText("description"); descLabel.setText("description");
descLabel.putClientProperty("FlatLaf.styleClass", "small"); descLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
descLabel.setEnabled(false); descLabel.setEnabled(false);
add(descLabel, "cell 0 1"); add(descLabel, "cell 0 1");
// JFormDesigner - End of component initialization //GEN-END:initComponents // JFormDesigner - End of component initialization //GEN-END:initComponents

View File

@@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.TitledBorder; import javax.swing.border.TitledBorder;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
@@ -74,6 +76,7 @@ public class FlatWindowDecorationsTest
} }
private List<Image> images; private List<Image> images;
private Timer refreshStateTimer;
FlatWindowDecorationsTest() { FlatWindowDecorationsTest() {
initComponents(); initComponents();
@@ -127,8 +130,54 @@ public class FlatWindowDecorationsTest
+ " @ " + bounds.x + ", " + bounds.y ); + " @ " + bounds.x + ", " + bounds.y );
} else } else
fullWindowContentButtonsBoundsField.setText( "null" ); fullWindowContentButtonsBoundsField.setText( "null" );
fullWindowContentButtonsBoundsLabel.setEnabled( bounds != null );
fullWindowContentButtonsBoundsField.setEnabled( bounds != null );
} ); } );
} }
if( window instanceof Frame ) {
AtomicInteger lastState = new AtomicInteger( -1 );
AtomicReference<Window> lastFullScreenWindow = new AtomicReference<>();
refreshStateTimer = new Timer( 500, e -> {
Frame frame = (Frame) window;
int state = frame.getExtendedState();
Window fullScreenWindow = window.getGraphicsConfiguration().getDevice().getFullScreenWindow();
if( state != lastState.get() || fullScreenWindow != lastFullScreenWindow.get() ) {
lastState.set( state );
lastFullScreenWindow.set( fullScreenWindow );
String s = "";
if( (state & Frame.ICONIFIED) != 0 )
s += "iconified ";
if( (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH )
s += "maximized ";
else {
if( (state & Frame.MAXIMIZED_HORIZ) != 0 )
s += "maximized-horizontal ";
if( (state & Frame.MAXIMIZED_VERT) != 0 )
s += "maximized-vertical ";
}
if( fullScreenWindow == window )
s += "full-screen ";
if( s.isEmpty() )
s = "normal";
frameStateField.setText( s );
}
} );
refreshStateTimer.start();
}
}
@Override
public void removeNotify() {
super.removeNotify();
if( refreshStateTimer != null ) {
refreshStateTimer.stop();
refreshStateTimer = null;
}
} }
private void updateDecorationStyleRadioButtons( JRootPane rootPane ) { private void updateDecorationStyleRadioButtons( JRootPane rootPane ) {
@@ -189,9 +238,10 @@ public class FlatWindowDecorationsTest
if( rightCompCheckBox.isSelected() ) { if( rightCompCheckBox.isSelected() ) {
rightStretchCompCheckBox.setSelected( false ); rightStretchCompCheckBox.setSelected( false );
tallCompCheckBox.setSelected( false );
JButton myButton = new JButton( "?" ); JButton myButton = new JButton( "?" );
myButton.putClientProperty( "JButton.buttonType", "toolBarButton" ); myButton.putClientProperty( FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_TOOLBAR_BUTTON );
myButton.setFocusable( false ); myButton.setFocusable( false );
menuBar.add( Box.createGlue() ); menuBar.add( Box.createGlue() );
@@ -207,6 +257,7 @@ public class FlatWindowDecorationsTest
if( rightStretchCompCheckBox.isSelected() ) { if( rightStretchCompCheckBox.isSelected() ) {
rightCompCheckBox.setSelected( false ); rightCompCheckBox.setSelected( false );
tallCompCheckBox.setSelected( false );
menuBar.add( Box.createGlue() ); menuBar.add( Box.createGlue() );
menuBar.add( new JProgressBar() ); menuBar.add( new JProgressBar() );
@@ -216,6 +267,20 @@ public class FlatWindowDecorationsTest
menuBar.repaint(); menuBar.repaint();
} }
private void tallCompChanged() {
removeNonMenusFromMenuBar();
if( tallCompCheckBox.isSelected() ) {
rightCompCheckBox.setSelected( false );
rightStretchCompCheckBox.setSelected( false );
menuBar.add( new JButton( "<html>large<br>button<br>large<br>button</html>" ) );
}
menuBar.revalidate();
menuBar.repaint();
}
private void removeNonMenusFromMenuBar() { private void removeNonMenusFromMenuBar() {
Component[] components = menuBar.getComponents(); Component[] components = menuBar.getComponents();
for( int i = components.length - 1; i >= 0; i-- ) { for( int i = components.length - 1; i >= 0; i-- ) {
@@ -434,7 +499,7 @@ debug*/
if( typeUtilityRadioButton.isSelected() ) if( typeUtilityRadioButton.isSelected() )
window.setType( Window.Type.UTILITY ); window.setType( Window.Type.UTILITY );
else if( typeSmallRadioButton.isSelected() ) else if( typeSmallRadioButton.isSelected() )
((RootPaneContainer)window).getRootPane().putClientProperty( "Window.style", "small" ); ((RootPaneContainer)window).getRootPane().putClientProperty( FlatClientProperties.WINDOW_STYLE, FlatClientProperties.WINDOW_STYLE_SMALL );
} }
private void decorationStyleChanged() { private void decorationStyleChanged() {
@@ -546,6 +611,16 @@ debug*/
} }
} }
private void titleBarHeightChanged() {
JRootPane rootPane = getWindowRootPane();
if( rootPane != null ) {
boolean enabled = titleBarHeightCheckBox.isSelected();
titleBarHeightField.setEnabled( enabled );
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_HEIGHT, enabled ? titleBarHeightField.getValue() : null );
}
}
private JRootPane getWindowRootPane() { private JRootPane getWindowRootPane() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
return (window instanceof RootPaneContainer) return (window instanceof RootPaneContainer)
@@ -572,12 +647,14 @@ debug*/
maximizedBoundsCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox();
JPanel panel4 = new JPanel(); JPanel panel4 = new JPanel();
showIconCheckBox = new FlatTriStateCheckBox(); showIconCheckBox = new FlatTriStateCheckBox();
titleBarHeightCheckBox = new JCheckBox();
showTitleCheckBox = new JCheckBox(); showTitleCheckBox = new JCheckBox();
titleBarHeightField = new JSpinner();
showIconifyCheckBox = new JCheckBox(); showIconifyCheckBox = new JCheckBox();
showMaximizeCheckBox = new JCheckBox(); showMaximizeCheckBox = new JCheckBox();
showCloseCheckBox = new JCheckBox(); showCloseCheckBox = new JCheckBox();
fullWindowContentCheckBox = new JCheckBox(); fullWindowContentCheckBox = new JCheckBox();
JLabel fullWindowContentButtonsBoundsLabel = new JLabel(); fullWindowContentButtonsBoundsLabel = new JLabel();
fullWindowContentButtonsBoundsField = new JLabel(); fullWindowContentButtonsBoundsField = new JLabel();
JPanel panel6 = new JPanel(); JPanel panel6 = new JPanel();
menuBarCheckBox = new JCheckBox(); menuBarCheckBox = new JCheckBox();
@@ -585,6 +662,7 @@ debug*/
menuBarVisibleCheckBox = new JCheckBox(); menuBarVisibleCheckBox = new JCheckBox();
rightCompCheckBox = new JCheckBox(); rightCompCheckBox = new JCheckBox();
rightStretchCompCheckBox = new JCheckBox(); rightStretchCompCheckBox = new JCheckBox();
tallCompCheckBox = new JCheckBox();
JPanel panel3 = new JPanel(); JPanel panel3 = new JPanel();
addMenuButton = new JButton(); addMenuButton = new JButton();
addGlueButton = new JButton(); addGlueButton = new JButton();
@@ -621,6 +699,9 @@ debug*/
typeUtilityRadioButton = new JRadioButton(); typeUtilityRadioButton = new JRadioButton();
typeSmallRadioButton = new JRadioButton(); typeSmallRadioButton = new JRadioButton();
showRectanglesCheckBox = new JCheckBox(); showRectanglesCheckBox = new JCheckBox();
JPanel hSpacer1 = new JPanel(null);
JLabel frameStateLabel = new JLabel();
frameStateField = new JLabel();
menuBar = new JMenuBar(); menuBar = new JMenuBar();
JMenu fileMenu = new JMenu(); JMenu fileMenu = new JMenu();
JMenuItem newMenuItem = new JMenuItem(); JMenuItem newMenuItem = new JMenuItem();
@@ -660,7 +741,8 @@ debug*/
"[fill]" + "[fill]" +
"[fill]" + "[fill]" +
"[]" + "[]" +
"[]")); "[]" +
"[40]"));
//======== panel7 ======== //======== panel7 ========
{ {
@@ -711,7 +793,8 @@ debug*/
panel4.setLayout(new MigLayout( panel4.setLayout(new MigLayout(
"ltr,hidemode 3,gap 0 0", "ltr,hidemode 3,gap 0 0",
// columns // columns
"[grow,left]", "[grow,left]" +
"[fill]",
// rows // rows
"[]" + "[]" +
"[]" + "[]" +
@@ -726,12 +809,23 @@ debug*/
showIconCheckBox.addActionListener(e -> showIconChanged()); showIconCheckBox.addActionListener(e -> showIconChanged());
panel4.add(showIconCheckBox, "cell 0 0"); panel4.add(showIconCheckBox, "cell 0 0");
//---- titleBarHeightCheckBox ----
titleBarHeightCheckBox.setText("Height:");
titleBarHeightCheckBox.addActionListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightCheckBox, "cell 1 0");
//---- showTitleCheckBox ---- //---- showTitleCheckBox ----
showTitleCheckBox.setText("show title"); showTitleCheckBox.setText("show title");
showTitleCheckBox.setSelected(true); showTitleCheckBox.setSelected(true);
showTitleCheckBox.addActionListener(e -> showTitleChanged()); showTitleCheckBox.addActionListener(e -> showTitleChanged());
panel4.add(showTitleCheckBox, "cell 0 1"); panel4.add(showTitleCheckBox, "cell 0 1");
//---- titleBarHeightField ----
titleBarHeightField.setEnabled(false);
titleBarHeightField.setModel(new SpinnerNumberModel(44, null, null, 2));
titleBarHeightField.addChangeListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightField, "cell 1 1");
//---- showIconifyCheckBox ---- //---- showIconifyCheckBox ----
showIconifyCheckBox.setText("show iconfiy"); showIconifyCheckBox.setText("show iconfiy");
showIconifyCheckBox.setSelected(true); showIconifyCheckBox.setSelected(true);
@@ -757,10 +851,12 @@ debug*/
//---- fullWindowContentButtonsBoundsLabel ---- //---- fullWindowContentButtonsBoundsLabel ----
fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:"); fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:");
fullWindowContentButtonsBoundsLabel.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6");
//---- fullWindowContentButtonsBoundsField ---- //---- fullWindowContentButtonsBoundsField ----
fullWindowContentButtonsBoundsField.setText("null"); fullWindowContentButtonsBoundsField.setText("null");
fullWindowContentButtonsBoundsField.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6");
} }
add(panel4, "cell 1 0"); add(panel4, "cell 1 0");
@@ -777,6 +873,7 @@ debug*/
"[]" + "[]" +
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]")); "[]"));
//---- menuBarCheckBox ---- //---- menuBarCheckBox ----
@@ -806,6 +903,11 @@ debug*/
rightStretchCompCheckBox.setText("right aligned stretching component"); rightStretchCompCheckBox.setText("right aligned stretching component");
rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged()); rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged());
panel6.add(rightStretchCompCheckBox, "cell 0 4"); panel6.add(rightStretchCompCheckBox, "cell 0 4");
//---- tallCompCheckBox ----
tallCompCheckBox.setText("tall component");
tallCompCheckBox.addActionListener(e -> tallCompChanged());
panel6.add(tallCompCheckBox, "cell 0 5");
} }
add(panel6, "cell 2 0"); add(panel6, "cell 2 0");
@@ -1039,6 +1141,16 @@ debug*/
showRectanglesCheckBox.setSelected(true); showRectanglesCheckBox.setSelected(true);
showRectanglesCheckBox.addActionListener(e -> showRectangles()); showRectanglesCheckBox.addActionListener(e -> showRectangles());
add(showRectanglesCheckBox, "cell 0 3"); add(showRectanglesCheckBox, "cell 0 3");
add(hSpacer1, "cell 2 3 2 1");
//---- frameStateLabel ----
frameStateLabel.setText("Frame state:");
add(frameStateLabel, "cell 2 3 2 1,alignx right,growx 0");
//---- frameStateField ----
frameStateField.setText("n/a");
frameStateField.setFont(frameStateField.getFont().deriveFont(frameStateField.getFont().getStyle() | Font.BOLD));
add(frameStateField, "cell 2 3 2 1,alignx right,growx 0");
//======== menuBar ======== //======== menuBar ========
{ {
@@ -1243,17 +1355,21 @@ debug*/
private JCheckBox fullScreenCheckBox; private JCheckBox fullScreenCheckBox;
private JCheckBox maximizedBoundsCheckBox; private JCheckBox maximizedBoundsCheckBox;
private FlatTriStateCheckBox showIconCheckBox; private FlatTriStateCheckBox showIconCheckBox;
private JCheckBox titleBarHeightCheckBox;
private JCheckBox showTitleCheckBox; private JCheckBox showTitleCheckBox;
private JSpinner titleBarHeightField;
private JCheckBox showIconifyCheckBox; private JCheckBox showIconifyCheckBox;
private JCheckBox showMaximizeCheckBox; private JCheckBox showMaximizeCheckBox;
private JCheckBox showCloseCheckBox; private JCheckBox showCloseCheckBox;
private JCheckBox fullWindowContentCheckBox; private JCheckBox fullWindowContentCheckBox;
private JLabel fullWindowContentButtonsBoundsLabel;
private JLabel fullWindowContentButtonsBoundsField; private JLabel fullWindowContentButtonsBoundsField;
private JCheckBox menuBarCheckBox; private JCheckBox menuBarCheckBox;
private JCheckBox menuBarEmbeddedCheckBox; private JCheckBox menuBarEmbeddedCheckBox;
private JCheckBox menuBarVisibleCheckBox; private JCheckBox menuBarVisibleCheckBox;
private JCheckBox rightCompCheckBox; private JCheckBox rightCompCheckBox;
private JCheckBox rightStretchCompCheckBox; private JCheckBox rightStretchCompCheckBox;
private JCheckBox tallCompCheckBox;
private JButton addMenuButton; private JButton addMenuButton;
private JButton addGlueButton; private JButton addGlueButton;
private JButton addCaptionButton; private JButton addCaptionButton;
@@ -1284,6 +1400,7 @@ debug*/
private JRadioButton typeUtilityRadioButton; private JRadioButton typeUtilityRadioButton;
private JRadioButton typeSmallRadioButton; private JRadioButton typeSmallRadioButton;
private JCheckBox showRectanglesCheckBox; private JCheckBox showRectanglesCheckBox;
private JLabel frameStateField;
private JMenuBar menuBar; private JMenuBar menuBar;
// JFormDesigner - End of variables declaration //GEN-END:variables // JFormDesigner - End of variables declaration //GEN-END:variables
} }

View File

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

Some files were not shown because too many files have changed in this diff Show More