mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
187 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97988e90b4 | ||
|
|
f71dbb2647 | ||
|
|
04ad21b5b6 | ||
|
|
ff722c0b34 | ||
|
|
34b19f00e4 | ||
|
|
286ce15146 | ||
|
|
abfaf86cd5 | ||
|
|
bc4c7b25d3 | ||
|
|
0863e289a1 | ||
|
|
4945378dd3 | ||
|
|
b178450e81 | ||
|
|
e3ffdd3b7c | ||
|
|
5326971287 | ||
|
|
cd34c08dc9 | ||
|
|
edee73e0ea | ||
|
|
54a53fb527 | ||
|
|
62b96fbccd | ||
|
|
42cbb0666d | ||
|
|
1465fbaabc | ||
|
|
5575854e68 | ||
|
|
640f2ba9a2 | ||
|
|
b221fd1894 | ||
|
|
b64ab09b88 | ||
|
|
2870ee5c51 | ||
|
|
23f8ce867b | ||
|
|
835a1f155b | ||
|
|
3925f198d9 | ||
|
|
d8e59f2cf3 | ||
|
|
666b99971d | ||
|
|
0ba7798cbd | ||
|
|
c486f695f2 | ||
|
|
0bc2513c46 | ||
|
|
bc3504378b | ||
|
|
94fc75dc78 | ||
|
|
681c0cd4fe | ||
|
|
f7495a0a5b | ||
|
|
dd44d3ed2d | ||
|
|
86a4d0ab12 | ||
|
|
b43c3a9e00 | ||
|
|
babc8aa55d | ||
|
|
5dc88a6210 | ||
|
|
d612b9f4b8 | ||
|
|
9b1ae5c74a | ||
|
|
143f96360b | ||
|
|
f5e6b90e02 | ||
|
|
f36886aeb3 | ||
|
|
d26eb2674f | ||
|
|
68b8769d0d | ||
|
|
7f37e884d3 | ||
|
|
a4dc1b4151 | ||
|
|
022a67929a | ||
|
|
f7c867fb97 | ||
|
|
f0685d179e | ||
|
|
c8eaf5f587 | ||
|
|
ed69049c08 | ||
|
|
ae4037ee82 | ||
|
|
411a2f6d29 | ||
|
|
f24b3a6022 | ||
|
|
ebacad2d04 | ||
|
|
76f436726f | ||
|
|
6c8f813e53 | ||
|
|
5f6cc719ad | ||
|
|
00858002de | ||
|
|
072cc3c488 | ||
|
|
1f594b2ba8 | ||
|
|
c32c00a5eb | ||
|
|
3a8a55a545 | ||
|
|
6c49b8bc4d | ||
|
|
cca9707f6b | ||
|
|
f30dd876e4 | ||
|
|
c6872d48b3 | ||
|
|
5e78b21df7 | ||
|
|
2ef87dc789 | ||
|
|
28904c34cc | ||
|
|
91f19bf94c | ||
|
|
0ea188f8db | ||
|
|
6c77b81277 | ||
|
|
ddee4ef526 | ||
|
|
f11f68282b | ||
|
|
ac0cceb09b | ||
|
|
a238fd4505 | ||
|
|
8dc6242889 | ||
|
|
d17fffb82a | ||
|
|
0ad3180b10 | ||
|
|
80ba75fdeb | ||
|
|
7027821c00 | ||
|
|
a3a49cef73 | ||
|
|
abf77d5399 | ||
|
|
6404b8de2a | ||
|
|
19055d5a18 | ||
|
|
c12adf12e7 | ||
|
|
b9c68fbe77 | ||
|
|
7bdfd49921 | ||
|
|
58fa2a5085 | ||
|
|
a400799db5 | ||
|
|
2a8e487c1f | ||
|
|
145631fd43 | ||
|
|
6a774d8c70 | ||
|
|
bfd746f981 | ||
|
|
3af54b7215 | ||
|
|
3ba9fc6c1c | ||
|
|
0a9ecd66a9 | ||
|
|
6991d6729e | ||
|
|
304cb0d57b | ||
|
|
41332de275 | ||
|
|
ef61ae504b | ||
|
|
f96baf1bc2 | ||
|
|
1462636e97 | ||
|
|
7e59a7f4af | ||
|
|
e9a21848bc | ||
|
|
1dcb251ecb | ||
|
|
3f33543cee | ||
|
|
84bd2088f2 | ||
|
|
4f4a3132c5 | ||
|
|
e064c934cb | ||
|
|
16fc3cabf2 | ||
|
|
7e002ff6c2 | ||
|
|
323c0c62c3 | ||
|
|
ff5bd301cc | ||
|
|
c37712b0f0 | ||
|
|
ee9e238592 | ||
|
|
da5d6fa157 | ||
|
|
d471f08b15 | ||
|
|
b97424f767 | ||
|
|
a20cfa6db3 | ||
|
|
6ac6698ecf | ||
|
|
8004d2761a | ||
|
|
25c2bbc851 | ||
|
|
33e37a7167 | ||
|
|
c29a276188 | ||
|
|
d1694aa8bd | ||
|
|
570cf6fc51 | ||
|
|
8eab86e489 | ||
|
|
566568f61a | ||
|
|
56a73a4d17 | ||
|
|
656d25b75e | ||
|
|
dcdc80ade3 | ||
|
|
09f2d65d5e | ||
|
|
b304d46f7e | ||
|
|
3391f971ec | ||
|
|
778fed27a5 | ||
|
|
1755dbc877 | ||
|
|
4e6f538519 | ||
|
|
a6ecb0ef85 | ||
|
|
438ec6ac5c | ||
|
|
8089e66642 | ||
|
|
d27e0561f2 | ||
|
|
97b21bfa8b | ||
|
|
ec4343ed30 | ||
|
|
948decb3b5 | ||
|
|
d510fee7f6 | ||
|
|
70b7a3d662 | ||
|
|
b142a6f31e | ||
|
|
14705a9b30 | ||
|
|
32b0f1ba10 | ||
|
|
cbffdf4900 | ||
|
|
1238da5e54 | ||
|
|
cba203be09 | ||
|
|
d89c6156b9 | ||
|
|
e06475b3b7 | ||
|
|
5ff99bd45e | ||
|
|
127dd6ac41 | ||
|
|
9e05384513 | ||
|
|
9ffda72ae3 | ||
|
|
72a4c00e72 | ||
|
|
c95e95ef67 | ||
|
|
0c0d4bffbf | ||
|
|
2a494b1d60 | ||
|
|
1463723e52 | ||
|
|
9ade48d078 | ||
|
|
7ba8274fd4 | ||
|
|
238443074c | ||
|
|
0decbec595 | ||
|
|
0eb77c7f72 | ||
|
|
f05df0db0a | ||
|
|
13fbaf1f74 | ||
|
|
969d2642de | ||
|
|
17ce6d39b4 | ||
|
|
261d2b1fe8 | ||
|
|
a54aeb3838 | ||
|
|
cc4f9a9db5 | ||
|
|
a311bac89b | ||
|
|
029f273dd9 | ||
|
|
bbbdd7e4d3 | ||
|
|
3f3ef6b24f | ||
|
|
8c3dfd4a36 | ||
|
|
af57599df9 |
124
.github/workflows/ci.yml
vendored
124
.github/workflows/ci.yml
vendored
@@ -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-' )) &&
|
||||||
@@ -88,27 +105,16 @@ jobs:
|
|||||||
distribution: temurin # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- name: Publish snapshot to Sonatype Central
|
||||||
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 }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_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/' ) &&
|
||||||
@@ -125,31 +131,19 @@ jobs:
|
|||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
run: ./gradlew publishToSonatype closeSonatypeStagingRepository :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
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"
|
|
||||||
|
|||||||
10
.github/workflows/fonts.yml
vendored
10
.github/workflows/fonts.yml
vendored
@@ -45,18 +45,18 @@ jobs:
|
|||||||
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
|
||||||
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- name: Publish snapshot to Sonatype Central
|
||||||
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )
|
if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||||
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||||
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )
|
||||||
|
|||||||
19
.github/workflows/natives.yml
vendored
19
.github/workflows/natives.yml
vendored
@@ -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
|
||||||
|
|||||||
6
.github/workflows/pr-snapshots.yml
vendored
6
.github/workflows/pr-snapshots.yml
vendored
@@ -28,10 +28,10 @@ jobs:
|
|||||||
distribution: temurin # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Publish PR snapshot to oss.sonatype.org
|
- name: Publish PR snapshot to Sonatype Central
|
||||||
run: >
|
run: >
|
||||||
./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||||
-Pgithub.event.pull_request.number=${{ github.event.pull_request.number }}
|
-Pgithub.event.pull_request.number=${{ github.event.pull_request.number }}
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@ build/
|
|||||||
.project
|
.project
|
||||||
.settings/
|
.settings/
|
||||||
.idea/
|
.idea/
|
||||||
|
.consulo/
|
||||||
out/
|
out/
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
|
|||||||
286
CHANGELOG.md
286
CHANGELOG.md
@@ -1,6 +1,282 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
## 3.6.1
|
||||||
|
|
||||||
|
- Extras: Support JSVG 2.0.0. Minimum JSVG version is now 1.6.0. (issue #997)
|
||||||
|
- FlatLaf window decorations (Windows 10/11 only): Improved diagonal window
|
||||||
|
resizing on top-left and top-right window corners. Top window resize area now
|
||||||
|
also covers iconify/maximize/close buttons. (issue #1015)
|
||||||
|
- ToggleButton: Styling `selectedForeground` did not work if `foreground` is
|
||||||
|
also styled. (issue #1017)
|
||||||
|
- JideSplitButton: Fixed updating popup when switching theme. (issue #1000)
|
||||||
|
- IntelliJ Themes: Fixed logging false errors when loading 3rd party
|
||||||
|
`.theme.json` files. (issue #990)
|
||||||
|
- Linux: Popups appeared in wrong position on multi-screen setup if primary
|
||||||
|
display is located below or right to secondary display. (see
|
||||||
|
[NetBeans issue #8532](https://github.com/apache/netbeans/issues/8532))
|
||||||
|
- macOS: Fixed popup flickering after theme change. (issue #1009)
|
||||||
|
- macOS with JetBrains Runtime: Fixed sometimes empty popups. (issue #1019)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.6
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- macOS: Re-enabled rounded popup border (see PR #772) on macOS 14.4+ (was
|
||||||
|
disabled in 3.5.x).
|
||||||
|
- Increased contrast of text for better readability: (PR #972; issue #762)
|
||||||
|
- In **FlatLaf Dark**, **FlatLaf Darcula** and many dark IntelliJ themes, made
|
||||||
|
all text colors brighter.
|
||||||
|
- In **FlatLaf Light**, **FlatLaf IntelliJ** and many light IntelliJ themes,
|
||||||
|
made disabled text colors slightly darker.
|
||||||
|
- In **FlatLaf macOS Light**, made disabled text colors darker.
|
||||||
|
- In **FlatLaf macOS Dark**, made text colors of "default" button and selected
|
||||||
|
ToggleButton lighter.
|
||||||
|
- 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)
|
||||||
|
- ScrollBar: Use rounded thumb also on Windows (as on macOS and Linux) and made
|
||||||
|
thumb slightly darker/lighter. (issue #918)
|
||||||
|
- Extras: `FlatSVGIcon` color filters now can access painting component to
|
||||||
|
implement component state based color mappings. (issue #906)
|
||||||
|
- Linux:
|
||||||
|
- Rounded iconify/maximize/close buttons if using FlatLaf window decorations.
|
||||||
|
(PR #971)
|
||||||
|
- Added `libflatlaf-linux-arm64.so` for Linux on ARM64. (issue #899)
|
||||||
|
- Use X11 window manager events to resize window, if FlatLaf window
|
||||||
|
decorations are enabled. This gives FlatLaf windows a more "native" feeling.
|
||||||
|
(issue #866)
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Updated to latest versions and fixed various issues.
|
||||||
|
- Support customizing through properties files. (issue #824)
|
||||||
|
- SwingX: Support `JXTipOfTheDay` component. (issue #980)
|
||||||
|
- Support key prefixes for Linux desktop environments (e.g. `[gnome]`, `[kde]`
|
||||||
|
or `[xfce]`) in properties files. (issue #974)
|
||||||
|
- Support custom key prefixes (e.g. `[win10]` or `[test]`) in properties files.
|
||||||
|
(issue #649)
|
||||||
|
- Support multi-prefixed keys (e.g. `[dark][gnome]TitlePane.buttonBackground`).
|
||||||
|
The value is only used if all prefixes match current platform/theme.
|
||||||
|
- Support new component border color to indicate success state (set client
|
||||||
|
property `JComponent.outline` to `success`). (PR #982, issue #945)
|
||||||
|
- Fonts: Updated **Inter** to
|
||||||
|
[v4.1](https://github.com/rsms/inter/releases/tag/v4.1).
|
||||||
|
|
||||||
|
#### 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: Fixed occasional maximizing of window when single-clicking the
|
||||||
|
window's title bar. (issue #637)
|
||||||
|
- Styling: MigLayout visual padding was not updated after applying style to
|
||||||
|
Button, ComboBox, Spinner, TextField (and subclasses) and ToggleButton. (issue
|
||||||
|
#965)
|
||||||
|
- Linux: Popups (menus and combobox lists) were not hidden when window is moved,
|
||||||
|
resized, maximized, restored, iconified or switched to another window. (issue
|
||||||
|
#962)
|
||||||
|
- Fixed loading FlatLaf UI delegate classes when using FlatLaf in special
|
||||||
|
application where multiple class loaders are involved. E.g. in Eclipse plugin
|
||||||
|
or in LibreOffice extension. (issues #955 and #851)
|
||||||
|
- HTML: Fixed rendering of `<hr noshade>` in dark themes. (issue #932)
|
||||||
|
- TextComponents: `selectAllOnFocusPolicy` related changes:
|
||||||
|
- No longer select all text if selection (or caret position) was changed by
|
||||||
|
application and `selectAllOnFocusPolicy` is `once` (the default). (issue
|
||||||
|
#983)
|
||||||
|
- FormattedTextField and Spinner: `selectAllOnFocusPolicy = once` behaves now
|
||||||
|
as `always` (was `never` before), which means that all text is selected when
|
||||||
|
component gains focus. This is because of special behavior of
|
||||||
|
`JFormattedTextField` that did not allow implementation of `once`.
|
||||||
|
- Client property `JTextField.selectAllOnFocusPolicy` now also works on
|
||||||
|
(editable) `JComboBox` and on `JSpinner`.
|
||||||
|
- Added client property `JTextField.selectAllOnMouseClick` to override UI
|
||||||
|
property `TextComponent.selectAllOnMouseClick`. (issue #961)
|
||||||
|
- For `selectAllOnMouseClick = true`, clicking with the mouse into the text
|
||||||
|
field, to focus it, now always selects all text, even if
|
||||||
|
`selectAllOnFocusPolicy` is `once`.
|
||||||
|
|
||||||
|
#### Incompatibilities
|
||||||
|
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Theme prefix in `IntelliJTheme$ThemeLaf.properties` changed from
|
||||||
|
`[theme-name]` to `{theme-name}`.
|
||||||
|
- Renamed classes in package
|
||||||
|
`com.formdev.flatlaf.intellijthemes.materialthemeuilite` from `Flat<theme>`
|
||||||
|
to `FlatMT<theme>`.
|
||||||
|
- Removed `Gruvbox Dark Medium` and `Gruvbox Dark Soft` themes.
|
||||||
|
- Prefixed keys in properties files (e.g. `[dark]Button.background` or
|
||||||
|
`[win]Button.arc`) are now handled earlier than before. In previous versions,
|
||||||
|
prefixed keys always had higher priority than unprefixed keys and did always
|
||||||
|
overwrite unprefixed keys. Now prefixed keys are handled in same order as
|
||||||
|
unprefixed keys, which means that if a key is prefixed and unprefixed (e.g.
|
||||||
|
`[win]Button.arc` and `Button.arc`), the one which is last specified in
|
||||||
|
properties file is used.\
|
||||||
|
Following worked in previous versions, but now `Button.arc` is always `6`:
|
||||||
|
~~~properties
|
||||||
|
[win]Button.arc = 12
|
||||||
|
Button.arc = 6
|
||||||
|
~~~
|
||||||
|
This works in new (and old) versions:
|
||||||
|
~~~properties
|
||||||
|
Button.arc = 6
|
||||||
|
[win]Button.arc = 12
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- HTML: Fixed occasional cutoff wrapped text when using multi-line text in HTML
|
||||||
|
tags `<h1>`...`<h6>`, `<code>`, `<kbd>`, `<big>`, `<small>` or `<samp>`.
|
||||||
|
(issue #873; regression in 3.5)
|
||||||
|
- Popup: Fixed `UnsupportedOperationException: PERPIXEL_TRANSLUCENT translucency
|
||||||
|
is not supported` exception on Haiku OS when showing popup (partly) outside of
|
||||||
|
window. (issue #869)
|
||||||
|
- HiDPI: Fixed occasional wrong repaint areas when using
|
||||||
|
`HiDPIUtils.installHiDPIRepaintManager()`. (see PR #864)
|
||||||
|
- Added system property `flatlaf.useSubMenuSafeTriangle` to allow disabling
|
||||||
|
submenu safe triangle (PR #490) for
|
||||||
|
[SWTSwing](https://github.com/Chrriis/SWTSwing). (issue #870)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.5
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- Table: Support rounded selection. (PR #856)
|
||||||
|
- Button and ToggleButton: Added border colors for pressed and selected states.
|
||||||
|
(issue #848)
|
||||||
|
- Label: Support painting background with rounded corners. (issue #842)
|
||||||
|
- Popup: Fixed flicker of popups (e.g. tooltips) while they are moving (e.g.
|
||||||
|
following mouse pointer). (issues #832 and #672)
|
||||||
|
- FileChooser: Wrap shortcuts in scroll pane. (issue #828)
|
||||||
|
- Theme Editor: On macOS, use larger window title bar. (PR #779)
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- macOS: Disabled rounded popup border (see PR #772) on macOS 14.4+ because it
|
||||||
|
may freeze the application and crash the macOS WindowServer process (reports
|
||||||
|
vary from Finder restarts to OS restarts). This is a temporary change until a
|
||||||
|
solution is found. See NetBeans issues
|
||||||
|
[apache/netbeans#7560](https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215)
|
||||||
|
and
|
||||||
|
[apache/netbeans#6647](https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442).
|
||||||
|
- FlatLaf window decorations: Window top border on Windows 10 in "full window
|
||||||
|
content" mode was not fully repainted when activating or deactivating window.
|
||||||
|
(issue #809)
|
||||||
|
- Button and ToggleButton: UI properties `[Toggle]Button.selectedForeground` and
|
||||||
|
`[Toggle]Button.pressedForeground` did not work for HTML text. (issue #848)
|
||||||
|
- HTML: Fixed font sizes for HTML tags `<h1>`...`<h6>`, `<code>`, `<kbd>`,
|
||||||
|
`<big>`, `<small>` and `<samp>` in HTML text for components Button, CheckBox,
|
||||||
|
RadioButton, MenuItem (and subclasses), JideLabel, JideButton, JXBusyLabel and
|
||||||
|
JXHyperlink. Also fixed for Label and ToolTip if using Java 11+.
|
||||||
|
- ScrollPane: Fixed/improved border painting at 125% - 175% scaling to avoid
|
||||||
|
different border thicknesses. (issue #743)
|
||||||
|
- Table: Fixed painting of alternating rows below table if auto-resize mode is
|
||||||
|
`JTable.AUTO_RESIZE_OFF` and table width is smaller than scroll pane (was not
|
||||||
|
updated when table width changed and was painted on wrong side in
|
||||||
|
right-to-left component orientation).
|
||||||
|
- Theme Editor: Fixed occasional empty window on startup on macOS.
|
||||||
|
- FlatLaf window decorations: Fixed black line sometimes painted on top of
|
||||||
|
(native) window border on Windows 11. (issue #852)
|
||||||
|
- HiDPI: Fixed incomplete component paintings at 125% or 175% scaling on Windows
|
||||||
|
where sometimes a 1px wide area at the right or bottom component edge is not
|
||||||
|
repainted. E.g. ScrollPane focus indicator border. (issues #860 and #582)
|
||||||
|
|
||||||
|
#### Incompatibilities
|
||||||
|
|
||||||
|
- ProgressBar: Log warning (including stack trace) when uninstalling
|
||||||
|
indeterminate progress bar UI or using `JProgressBar.setIndeterminate(false)`
|
||||||
|
not on AWT thread, because this may throw NPE in `FlatProgressBarUI.paint()`.
|
||||||
|
(issues #841 and #830)
|
||||||
|
- Panel: Rounded background of panel with rounded corners is now painted even if
|
||||||
|
panel is not opaque. (issue #840)
|
||||||
|
|
||||||
|
|
||||||
## 3.4.1
|
## 3.4.1
|
||||||
|
|
||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
@@ -10,7 +286,7 @@ FlatLaf Change Log
|
|||||||
- TabbedPane: Fixed swapped back and forward scroll buttons when using
|
- TabbedPane: Fixed swapped back and forward scroll buttons when using
|
||||||
`TabbedPane.scrollButtonsPlacement = trailing` (regression in FlatLaf 3.3).
|
`TabbedPane.scrollButtonsPlacement = trailing` (regression in FlatLaf 3.3).
|
||||||
- Fixed missing window top border on Windows 10 in "full window content" mode.
|
- Fixed missing window top border on Windows 10 in "full window content" mode.
|
||||||
(issue 809)
|
(issue #809)
|
||||||
- Extras:
|
- Extras:
|
||||||
- `FlatSVGIcon` color filters now support linear gradients. (PR #817)
|
- `FlatSVGIcon` color filters now support linear gradients. (PR #817)
|
||||||
- `FlatSVGIcon`: Use log level `CONFIG` instead of `SEVERE` and allow
|
- `FlatSVGIcon`: Use log level `CONFIG` instead of `SEVERE` and allow
|
||||||
@@ -54,8 +330,8 @@ FlatLaf Change Log
|
|||||||
- Improved log messages for loading fails.
|
- Improved log messages for loading fails.
|
||||||
- Fonts: Updated **Inter** to
|
- Fonts: Updated **Inter** to
|
||||||
[v4.0](https://github.com/rsms/inter/releases/tag/v4.0).
|
[v4.0](https://github.com/rsms/inter/releases/tag/v4.0).
|
||||||
- Table: Select all text in cell editor when starting editing using `F2` key.
|
- Table: Select all text in cell editor when starting editing using `F2` key on
|
||||||
(issue 652)
|
Windows or Linux. (issue #652)
|
||||||
|
|
||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
|
|
||||||
@@ -83,7 +359,7 @@ FlatLaf Change Log
|
|||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
|
|
||||||
- Button and ToggleButton: Selected buttons did not use explicitly set
|
- Button and ToggleButton: Selected buttons did not use explicitly set
|
||||||
foreground color. (issue 756)
|
foreground color. (issue #756)
|
||||||
- FileChooser: Catch NPE in Java 21 when getting icon for `.exe` files that use
|
- FileChooser: Catch NPE in Java 21 when getting icon for `.exe` files that use
|
||||||
default Windows exe icon. (see
|
default Windows exe icon. (see
|
||||||
[JDK-8320692](https://bugs.openjdk.org/browse/JDK-8320692))
|
[JDK-8320692](https://bugs.openjdk.org/browse/JDK-8320692))
|
||||||
@@ -836,7 +1112,7 @@ FlatLaf Change Log
|
|||||||
- Native window decorations (Windows 10 only):
|
- Native window decorations (Windows 10 only):
|
||||||
- Fixed occasional application crash in `flatlaf-windows.dll`. (issue #357)
|
- Fixed occasional application crash in `flatlaf-windows.dll`. (issue #357)
|
||||||
- When window is initially shown, fill background with window background color
|
- When window is initially shown, fill background with window background color
|
||||||
(instead of white), which avoids flickering in dark themes. (issue 339)
|
(instead of white), which avoids flickering in dark themes. (issue #339)
|
||||||
- When resizing a window at the right/bottom edge, then first fill the new
|
- When resizing a window at the right/bottom edge, then first fill the new
|
||||||
space with the window background color (instead of black) before the layout
|
space with the window background color (instead of black) before the layout
|
||||||
is updated.
|
is updated.
|
||||||
|
|||||||
112
README.md
112
README.md
@@ -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>
|
||||||
|
|
||||||
|
<!-- [](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>
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<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
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -75,10 +83,10 @@ application.
|
|||||||
### Snapshots
|
### Snapshots
|
||||||
|
|
||||||
FlatLaf snapshot binaries are available on
|
FlatLaf snapshot binaries are available on
|
||||||
[Sonatype OSSRH](https://oss.sonatype.org/content/repositories/snapshots/com/formdev/flatlaf/).
|
[Sonatype Central](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/com/formdev/flatlaf/).
|
||||||
To access the latest snapshot, change the FlatLaf version in your dependencies
|
To access the latest snapshot, change the FlatLaf version in your dependencies
|
||||||
to `<version>-SNAPSHOT` (e.g. `0.27-SNAPSHOT`) and add the repository
|
to `<version>-SNAPSHOT` (e.g. `3.7-SNAPSHOT`) and add the repository
|
||||||
`https://oss.sonatype.org/content/repositories/snapshots/` to your build (see
|
`https://central.sonatype.com/repository/maven-snapshots/` to your build (see
|
||||||
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
||||||
and
|
and
|
||||||
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
||||||
@@ -176,11 +184,16 @@ Applications using FlatLaf
|
|||||||
relational data browsing tool
|
relational data browsing tool
|
||||||
-  [MagicPlot](https://magicplot.com/) (**commercial**) -
|
-  [MagicPlot](https://magicplot.com/) (**commercial**) -
|
||||||
Software for nonlinear fitting, plotting and data analysis
|
Software for nonlinear fitting, plotting and data analysis
|
||||||
-  [Constellation](https://www.constellation-app.com/) -
|
- [Constellation](https://www.constellation-app.com/) - Data Visualization and
|
||||||
Data Visualization and Analytics (based on NetBeans platform)
|
Analytics (based on NetBeans platform)
|
||||||
- 
|
- [Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
|
||||||
[Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
|
|
||||||
client
|
client
|
||||||
|
- 
|
||||||
|
[RedisFront](https://github.com/dromara/RedisFront/blob/master/README_EN.md) -
|
||||||
|
Cross-platform redis GUI
|
||||||
|
- 
|
||||||
|
[Zettelkasten](https://github.com/Zettelkasten-Team/Zettelkasten) - knowledge
|
||||||
|
management tool
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
@@ -189,11 +202,9 @@ Applications using FlatLaf
|
|||||||
- 
|
- 
|
||||||
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
||||||
(**commercial**) - the leading software for web security testing
|
(**commercial**) - the leading software for web security testing
|
||||||
- 
|
- [Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
||||||
[Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
|
||||||
reverse engineering (SRE) framework
|
reverse engineering (SRE) framework
|
||||||
-  [jadx](https://github.com/skylot/jadx) - Dex to Java
|
- [jadx](https://github.com/skylot/jadx) - Dex to Java decompiler
|
||||||
decompiler
|
|
||||||
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||||
FlatLaf themes to Burp Suite
|
FlatLaf themes to Burp Suite
|
||||||
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
||||||
@@ -205,19 +216,24 @@ Applications using FlatLaf
|
|||||||
|
|
||||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
||||||
- [KeyStore Explorer](https://keystore-explorer.org/)
|
- [KeyStore Explorer](https://keystore-explorer.org/)
|
||||||
- 
|
- [muCommander](https://github.com/mucommander/mucommander) - lightweight
|
||||||
[muCommander](https://github.com/mucommander/mucommander) - lightweight
|
|
||||||
cross-platform file manager
|
cross-platform file manager
|
||||||
-  [Guiffy](https://www.guiffy.com/) (**commercial**) -
|
- [Guiffy](https://www.guiffy.com/) (**commercial**) - advanced cross-platform
|
||||||
advanced cross-platform Diff/Merge
|
Diff/Merge
|
||||||
-  [HashGarten](https://github.com/jonelo/HashGarten) -
|
- [HashGarten](https://github.com/jonelo/HashGarten) - cross-platform Swing GUI
|
||||||
cross-platform Swing GUI for Jacksum
|
for Jacksum
|
||||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||||
IDE for Pseudo-Assembler
|
IDE for Pseudo-Assembler
|
||||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
||||||
language created to learn programming
|
language created to learn programming
|
||||||
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
||||||
systems development platform
|
systems development platform
|
||||||
|
-  [Consulo](https://github.com/consulo/consulo) - open
|
||||||
|
source cross-platform multi-language IDE (Java, .NET, JS, etc)
|
||||||
|
- [Convertigo](https://github.com/convertigo/convertigo) - low code & no code
|
||||||
|
mobile & web platform
|
||||||
|
-  [EduMIPS64](https://github.com/EduMIPS64/edumips64) -
|
||||||
|
visual MIPS64 CPU simulator
|
||||||
|
|
||||||
### Electrical
|
### Electrical
|
||||||
|
|
||||||
@@ -225,6 +241,11 @@ Applications using FlatLaf
|
|||||||
designing, simulating and explaining digital circuits
|
designing, simulating and explaining digital circuits
|
||||||
- [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) -
|
- [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) -
|
||||||
Digital logic design tool and simulator
|
Digital logic design tool and simulator
|
||||||
|
-  [OpenPnP](https://github.com/openpnp/openpnp) - SMT
|
||||||
|
Pick and Place Hardware and Software
|
||||||
|
- 
|
||||||
|
[TrainControl](https://github.com/bob123456678/TrainControl) - control Marklin
|
||||||
|
/ Trix / DCC digital model train layout
|
||||||
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
|
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
|
||||||
for plotters, especially the wall-hanging polargraph
|
for plotters, especially the wall-hanging polargraph
|
||||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
|
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
|
||||||
@@ -239,8 +260,10 @@ Applications using FlatLaf
|
|||||||
|
|
||||||
-  [jAlbum](https://jalbum.net/) (**commercial**) -
|
-  [jAlbum](https://jalbum.net/) (**commercial**) -
|
||||||
creates photo album websites
|
creates photo album websites
|
||||||
-  [MediathekView](https://mediathekview.de/) - search in
|
- [MediathekView](https://mediathekview.de/) - search in media libraries of
|
||||||
media libraries of various German broadcasters
|
various German broadcasters
|
||||||
|
-  [Pixelitor](https://github.com/lbalazscs/Pixelitor) -
|
||||||
|
image editor
|
||||||
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
|
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
|
||||||
sequences
|
sequences
|
||||||
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
|
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
|
||||||
@@ -257,18 +280,23 @@ Applications using FlatLaf
|
|||||||
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
|
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
|
||||||
ease
|
ease
|
||||||
|
|
||||||
### Modelling
|
### Modelling / Planning
|
||||||
|
|
||||||
-  [Astah](https://astah.net/) (**commercial**) - create
|
-  [Gephi](https://github.com/gephi/gephi) - the Open
|
||||||
UML, ER Diagram, Flowchart, Data Flow Diagram, Requirement Diagram, SysML
|
Graph Viz Platform
|
||||||
diagrams and more
|
- [Astah](https://astah.net/) (**commercial**) - create UML, ER Diagram,
|
||||||
|
Flowchart, Data Flow Diagram, Requirement Diagram, SysML diagrams and more
|
||||||
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||||
Application System
|
Application System
|
||||||
|
-  [StarPlan](https://www.progotec.de/) (**commercial**) -
|
||||||
|
die Stundenplan Software für Bildungseinrichtungen
|
||||||
|
-  [SSPlot](https://github.com/babaissarkar/ssplot) -
|
||||||
|
plotting utility for plotting CSV data
|
||||||
|
|
||||||
### Documents
|
### Documents
|
||||||
|
|
||||||
-  [Big Faceless (BFO) PDF Viewer](https://bfo.com/)
|
- [Big Faceless (BFO) PDF Viewer](https://bfo.com/) (**commercial**) - Swing PDF
|
||||||
(**commercial**) - Swing PDF Viewer
|
Viewer
|
||||||
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
|
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
|
||||||
review and edit PDF documents
|
review and edit PDF documents
|
||||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
|
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
|
||||||
@@ -286,6 +314,9 @@ Applications using FlatLaf
|
|||||||
|
|
||||||
### Business / Legal
|
### Business / Legal
|
||||||
|
|
||||||
|
-  
|
||||||
|
[Lisheane ERP](https://www.lisheane.ch/) (**commercial**) - backoffice
|
||||||
|
applikation
|
||||||
- 
|
- 
|
||||||
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||||
-  [Jeyla Studio](https://www.jeylastudio.com/) -
|
-  [Jeyla Studio](https://www.jeylastudio.com/) -
|
||||||
@@ -302,20 +333,20 @@ Applications using FlatLaf
|
|||||||
|
|
||||||
### Messaging
|
### Messaging
|
||||||
|
|
||||||
-  [Spark](https://github.com/igniterealtime/Spark) -
|
- [Spark](https://github.com/igniterealtime/Spark) - cross-platform IM client
|
||||||
cross-platform IM client optimized for businesses and organizations
|
optimized for businesses and organizations
|
||||||
-  [Chatty](https://github.com/chatty/chatty) - Twitch
|
- [Chatty](https://github.com/chatty/chatty) - Twitch Chat Client
|
||||||
Chat Client
|
|
||||||
|
|
||||||
### Gaming
|
### Gaming
|
||||||
|
|
||||||
-  
|
-  [BGBlitz](https://www.bgblitz.com/)
|
||||||
[BGBlitz](https://www.bgblitz.com/) (**commercial**) - professional Backgammon
|
(**commercial**) - professional Backgammon
|
||||||
-  [MCreator](https://github.com/MCreator/MCreator) -
|
-  [josé](https://peteschaefer.github.io/jose/) - a
|
||||||
software used to make Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons,
|
graphical chess tool
|
||||||
and data packs without programming knowledge
|
-  [MCreator](https://github.com/MCreator/MCreator) - make
|
||||||
-  [MapTool](https://github.com/RPTools/maptool) - virtual
|
Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons, and data packs
|
||||||
Tabletop for playing role-playing games
|
- [MapTool](https://github.com/RPTools/maptool) - virtual Tabletop for playing
|
||||||
|
role-playing games
|
||||||
- [MegaMek](https://github.com/MegaMek/megamek),
|
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||||
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||||
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
||||||
@@ -327,8 +358,7 @@ Applications using FlatLaf
|
|||||||
|
|
||||||
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||||
OSHI, to view information about the system and hardware
|
OSHI, to view information about the system and hardware
|
||||||
- 
|
- [Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
||||||
[Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
|
||||||
GUI for monitoring and managing various aspects of a Linux system
|
GUI for monitoring and managing various aspects of a Linux system
|
||||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||||
@@ -337,6 +367,8 @@ Applications using FlatLaf
|
|||||||
easy
|
easy
|
||||||
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
||||||
and fastboot commands easier to use
|
and fastboot commands easier to use
|
||||||
|
-  [Termora](https://github.com/TermoraDev/termora) -
|
||||||
|
Terminal emulator and SSH client
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import net.ltgt.gradle.errorprone.errorprone
|
import net.ltgt.gradle.errorprone.errorprone
|
||||||
|
|
||||||
|
group = "com.formdev"
|
||||||
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
||||||
|
|
||||||
// for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT'
|
// for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT'
|
||||||
@@ -49,6 +50,7 @@ println()
|
|||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
|
alias( libs.plugins.gradle.nexus.publish.plugin )
|
||||||
alias( libs.plugins.errorprone ) apply false
|
alias( libs.plugins.errorprone ) apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,3 +145,20 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nexusPublishing {
|
||||||
|
repositories {
|
||||||
|
sonatype {
|
||||||
|
// see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/
|
||||||
|
nexusUrl = uri( "https://ossrh-staging-api.central.sonatype.com/service/local/" )
|
||||||
|
snapshotRepositoryUrl = uri( "https://central.sonatype.com/repository/maven-snapshots/" )
|
||||||
|
|
||||||
|
// get from gradle.properties
|
||||||
|
val sonatypeUsername: String? by project
|
||||||
|
val sonatypePassword: String? by project
|
||||||
|
|
||||||
|
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername
|
||||||
|
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,24 +86,26 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "OSSRH"
|
name = "MavenCentral"
|
||||||
|
|
||||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
val releasesRepoUrl = "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"
|
||||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
val snapshotsRepoUrl = "https://central.sonatype.com/repository/maven-snapshots/"
|
||||||
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
// get from gradle.properties
|
// get from gradle.properties
|
||||||
val ossrhUsername: String? by project
|
val sonatypeUsername: String? by project
|
||||||
val ossrhPassword: String? by project
|
val sonatypePassword: String? by project
|
||||||
|
|
||||||
username = System.getenv( "OSSRH_USERNAME" ) ?: ossrhUsername
|
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername
|
||||||
password = System.getenv( "OSSRH_PASSWORD" ) ?: ossrhPassword
|
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
signing {
|
signing {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
||||||
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
||||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||||
|
|||||||
@@ -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" ),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Signature file v4.1
|
#Signature file v4.1
|
||||||
#Version 3.4
|
#Version 3.6.1
|
||||||
|
|
||||||
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"
|
||||||
@@ -24,6 +24,7 @@ fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHei
|
|||||||
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
||||||
fld public final static java.lang.String OUTLINE = "JComponent.outline"
|
fld public final static java.lang.String OUTLINE = "JComponent.outline"
|
||||||
fld public final static java.lang.String OUTLINE_ERROR = "error"
|
fld public final static java.lang.String OUTLINE_ERROR = "error"
|
||||||
|
fld public final static java.lang.String OUTLINE_SUCCESS = "success"
|
||||||
fld public final static java.lang.String OUTLINE_WARNING = "warning"
|
fld public final static java.lang.String OUTLINE_WARNING = "warning"
|
||||||
fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placeholderText"
|
fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placeholderText"
|
||||||
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
|
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
|
||||||
@@ -40,6 +41,7 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY = "JTextFiel
|
|||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
|
||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
||||||
|
fld public final static java.lang.String SELECT_ALL_ON_MOUSE_CLICK = "JTextField.selectAllOnMouseClick"
|
||||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
|
||||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
|
||||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
|
||||||
@@ -100,12 +102,14 @@ 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"
|
||||||
fld public final static java.lang.String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize"
|
fld public final static java.lang.String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize"
|
||||||
fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle"
|
fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle"
|
||||||
fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection"
|
fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection"
|
||||||
|
fld public final static java.lang.String TREE_WIDE_CELL_RENDERER = "JTree.wideCellRenderer"
|
||||||
fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection"
|
fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection"
|
||||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"
|
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"
|
||||||
fld public final static java.lang.String WINDOW_STYLE = "Window.style"
|
fld public final static java.lang.String WINDOW_STYLE = "Window.style"
|
||||||
@@ -219,10 +223,14 @@ meth public static java.lang.String getPreferredFontFamily()
|
|||||||
meth public static java.lang.String getPreferredLightFontFamily()
|
meth public static java.lang.String getPreferredLightFontFamily()
|
||||||
meth public static java.lang.String getPreferredMonospacedFontFamily()
|
meth public static java.lang.String getPreferredMonospacedFontFamily()
|
||||||
meth public static java.lang.String getPreferredSemiboldFontFamily()
|
meth public static java.lang.String getPreferredSemiboldFontFamily()
|
||||||
|
meth public static java.lang.String getUIKeyLightOrDarkPrefix(boolean)
|
||||||
meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleableInfos(javax.swing.JComponent)
|
meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleableInfos(javax.swing.JComponent)
|
||||||
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.Set<java.lang.String> getUIKeyPlatformPrefixes()
|
||||||
|
meth public static java.util.Set<java.lang.String> getUIKeySpecialPrefixes()
|
||||||
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>)
|
||||||
@@ -253,7 +261,7 @@ meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.Strin
|
|||||||
meth public void uninitialize()
|
meth public void uninitialize()
|
||||||
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||||
supr javax.swing.plaf.basic.BasicLookAndFeel
|
supr javax.swing.plaf.basic.BasicLookAndFeel
|
||||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,updateUIPending
|
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,linuxPopupMenuCanceler,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,uiKeyPlatformPrefixes,uiKeySpecialPrefixes,updateUIPending
|
||||||
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
||||||
|
|
||||||
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
||||||
@@ -296,6 +304,8 @@ fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flat
|
|||||||
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
||||||
anno 0 java.lang.Deprecated()
|
anno 0 java.lang.Deprecated()
|
||||||
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
||||||
|
fld public final static java.lang.String USE_ROUNDED_POPUP_BORDER = "flatlaf.useRoundedPopupBorder"
|
||||||
|
fld public final static java.lang.String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle"
|
||||||
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
||||||
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
||||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"
|
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"
|
||||||
@@ -314,7 +324,7 @@ meth public static boolean setup(java.io.InputStream)
|
|||||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
|
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
|
||||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
|
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludes,uiKeyInverseMapping,uiKeyMapping
|
hfds checkboxDuplicateColors,checkboxKeyMapping,jsonColors,jsonIcons,jsonUI,namedColors,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludesContains,uiKeyExcludesStartsWith,uiKeyInverseMapping,uiKeyMapping
|
||||||
|
|
||||||
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
|
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
|
||||||
outer com.formdev.flatlaf.IntelliJTheme
|
outer com.formdev.flatlaf.IntelliJTheme
|
||||||
@@ -409,6 +419,7 @@ innr public static Fade
|
|||||||
innr public static HSLChange
|
innr public static HSLChange
|
||||||
innr public static HSLIncreaseDecrease
|
innr public static HSLIncreaseDecrease
|
||||||
innr public static Mix
|
innr public static Mix
|
||||||
|
innr public static Mix2
|
||||||
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
||||||
meth public static float clamp(float)
|
meth public static float clamp(float)
|
||||||
meth public static float luma(java.awt.Color)
|
meth public static float luma(java.awt.Color)
|
||||||
@@ -470,6 +481,16 @@ meth public java.lang.String toString()
|
|||||||
meth public void apply(float[])
|
meth public void apply(float[])
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|
||||||
|
CLSS public static com.formdev.flatlaf.util.ColorFunctions$Mix2
|
||||||
|
outer com.formdev.flatlaf.util.ColorFunctions
|
||||||
|
cons public init(java.awt.Color,float)
|
||||||
|
fld public final float weight
|
||||||
|
fld public final java.awt.Color color1
|
||||||
|
intf com.formdev.flatlaf.util.ColorFunctions$ColorFunction
|
||||||
|
meth public java.lang.String toString()
|
||||||
|
meth public void apply(float[])
|
||||||
|
supr java.lang.Object
|
||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.CubicBezierEasing
|
CLSS public com.formdev.flatlaf.util.CubicBezierEasing
|
||||||
cons public init(float,float,float,float)
|
cons public init(float,float,float,float)
|
||||||
fld public final static com.formdev.flatlaf.util.CubicBezierEasing EASE
|
fld public final static com.formdev.flatlaf.util.CubicBezierEasing EASE
|
||||||
@@ -629,16 +650,33 @@ hfds alpha,hsl,rgb
|
|||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.HiDPIUtils
|
CLSS public com.formdev.flatlaf.util.HiDPIUtils
|
||||||
cons public init()
|
cons public init()
|
||||||
|
innr public abstract interface static DirtyRegionCallback
|
||||||
innr public abstract interface static Painter
|
innr public abstract interface static Painter
|
||||||
|
innr public static HiDPIRepaintManager
|
||||||
meth public static float computeTextYCorrection(java.awt.Graphics2D)
|
meth public static float computeTextYCorrection(java.awt.Graphics2D)
|
||||||
meth public static java.awt.Graphics2D createGraphicsTextYCorrection(java.awt.Graphics2D)
|
meth public static java.awt.Graphics2D createGraphicsTextYCorrection(java.awt.Graphics2D)
|
||||||
|
meth public static void addDirtyRegion(javax.swing.JComponent,int,int,int,int,com.formdev.flatlaf.util.HiDPIUtils$DirtyRegionCallback)
|
||||||
meth public static void drawStringUnderlineCharAtWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int,int)
|
meth public static void drawStringUnderlineCharAtWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int,int)
|
||||||
meth public static void drawStringWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int)
|
meth public static void drawStringWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int)
|
||||||
|
meth public static void installHiDPIRepaintManager()
|
||||||
meth public static void paintAtScale1x(java.awt.Graphics2D,int,int,int,int,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
meth public static void paintAtScale1x(java.awt.Graphics2D,int,int,int,int,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
||||||
meth public static void paintAtScale1x(java.awt.Graphics2D,javax.swing.JComponent,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
meth public static void paintAtScale1x(java.awt.Graphics2D,javax.swing.JComponent,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
||||||
|
meth public static void repaint(java.awt.Component)
|
||||||
|
meth public static void repaint(java.awt.Component,int,int,int,int)
|
||||||
|
meth public static void repaint(java.awt.Component,java.awt.Rectangle)
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
hfds CORRECTION_INTER,CORRECTION_OPEN_SANS,CORRECTION_SEGOE_UI,CORRECTION_TAHOMA,SCALE_FACTORS,useDebugScaleFactor,useTextYCorrection
|
hfds CORRECTION_INTER,CORRECTION_OPEN_SANS,CORRECTION_SEGOE_UI,CORRECTION_TAHOMA,SCALE_FACTORS,useDebugScaleFactor,useTextYCorrection
|
||||||
|
|
||||||
|
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$DirtyRegionCallback
|
||||||
|
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||||
|
meth public abstract void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||||
|
|
||||||
|
CLSS public static com.formdev.flatlaf.util.HiDPIUtils$HiDPIRepaintManager
|
||||||
|
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||||
|
cons public init()
|
||||||
|
meth public void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||||
|
supr javax.swing.RepaintManager
|
||||||
|
|
||||||
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$Painter
|
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$Painter
|
||||||
outer com.formdev.flatlaf.util.HiDPIUtils
|
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||||
meth public abstract void paint(java.awt.Graphics2D,int,int,int,int,double)
|
meth public abstract void paint(java.awt.Graphics2D,int,int,int,int,double)
|
||||||
@@ -734,6 +772,7 @@ supr java.lang.Object
|
|||||||
CLSS public com.formdev.flatlaf.util.SystemInfo
|
CLSS public com.formdev.flatlaf.util.SystemInfo
|
||||||
cons public init()
|
cons public init()
|
||||||
fld public final static boolean isAARCH64
|
fld public final static boolean isAARCH64
|
||||||
|
fld public final static boolean isGNOME
|
||||||
fld public final static boolean isJava_11_orLater
|
fld public final static boolean isJava_11_orLater
|
||||||
fld public final static boolean isJava_12_orLater
|
fld public final static boolean isJava_12_orLater
|
||||||
fld public final static boolean isJava_15_orLater
|
fld public final static boolean isJava_15_orLater
|
||||||
@@ -750,6 +789,7 @@ fld public final static boolean isMacOS_10_11_ElCapitan_orLater
|
|||||||
fld public final static boolean isMacOS_10_14_Mojave_orLater
|
fld public final static boolean isMacOS_10_14_Mojave_orLater
|
||||||
fld public final static boolean isMacOS_10_15_Catalina_orLater
|
fld public final static boolean isMacOS_10_15_Catalina_orLater
|
||||||
fld public final static boolean isProjector
|
fld public final static boolean isProjector
|
||||||
|
fld public final static boolean isUnknownOS
|
||||||
fld public final static boolean isWebswing
|
fld public final static boolean isWebswing
|
||||||
fld public final static boolean isWinPE
|
fld public final static boolean isWinPE
|
||||||
fld public final static boolean isWindows
|
fld public final static boolean isWindows
|
||||||
@@ -1137,6 +1177,31 @@ meth public void provideErrorFeedback(java.awt.Component)
|
|||||||
meth public void uninitialize()
|
meth public void uninitialize()
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|
||||||
|
CLSS public javax.swing.RepaintManager
|
||||||
|
cons public init()
|
||||||
|
meth public boolean isCompletelyDirty(javax.swing.JComponent)
|
||||||
|
meth public boolean isDoubleBufferingEnabled()
|
||||||
|
meth public java.awt.Dimension getDoubleBufferMaximumSize()
|
||||||
|
meth public java.awt.Image getOffscreenBuffer(java.awt.Component,int,int)
|
||||||
|
meth public java.awt.Image getVolatileOffscreenBuffer(java.awt.Component,int,int)
|
||||||
|
meth public java.awt.Rectangle getDirtyRegion(javax.swing.JComponent)
|
||||||
|
meth public java.lang.String toString()
|
||||||
|
meth public static javax.swing.RepaintManager currentManager(java.awt.Component)
|
||||||
|
meth public static javax.swing.RepaintManager currentManager(javax.swing.JComponent)
|
||||||
|
meth public static void setCurrentManager(javax.swing.RepaintManager)
|
||||||
|
meth public void addDirtyRegion(java.applet.Applet,int,int,int,int)
|
||||||
|
meth public void addDirtyRegion(java.awt.Window,int,int,int,int)
|
||||||
|
meth public void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||||
|
meth public void addInvalidComponent(javax.swing.JComponent)
|
||||||
|
meth public void markCompletelyClean(javax.swing.JComponent)
|
||||||
|
meth public void markCompletelyDirty(javax.swing.JComponent)
|
||||||
|
meth public void paintDirtyRegions()
|
||||||
|
meth public void removeInvalidComponent(javax.swing.JComponent)
|
||||||
|
meth public void setDoubleBufferMaximumSize(java.awt.Dimension)
|
||||||
|
meth public void setDoubleBufferingEnabled(boolean)
|
||||||
|
meth public void validateInvalidComponents()
|
||||||
|
supr java.lang.Object
|
||||||
|
|
||||||
CLSS public abstract javax.swing.border.AbstractBorder
|
CLSS public abstract javax.swing.border.AbstractBorder
|
||||||
cons public init()
|
cons public init()
|
||||||
intf java.io.Serializable
|
intf java.io.Serializable
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import java.awt.IllegalComponentStateException;
|
|||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -220,6 +222,7 @@ public interface FlatClientProperties
|
|||||||
* <strong>Allowed Values</strong>
|
* <strong>Allowed Values</strong>
|
||||||
* {@link #OUTLINE_ERROR},
|
* {@link #OUTLINE_ERROR},
|
||||||
* {@link #OUTLINE_WARNING},
|
* {@link #OUTLINE_WARNING},
|
||||||
|
* {@link #OUTLINE_SUCCESS},
|
||||||
* any color (type {@link java.awt.Color}) or
|
* any color (type {@link java.awt.Color}) or
|
||||||
* an array of two colors (type {@link java.awt.Color}[2]) where the first color
|
* an array of two colors (type {@link java.awt.Color}[2]) where the first color
|
||||||
* is for focused state and the second for unfocused state
|
* is for focused state and the second for unfocused state
|
||||||
@@ -240,6 +243,14 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String OUTLINE_WARNING = "warning";
|
String OUTLINE_WARNING = "warning";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the component border in another color (usually greenish) to indicate a success.
|
||||||
|
*
|
||||||
|
* @see #OUTLINE
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
String OUTLINE_SUCCESS = "success";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a callback that is invoked to check whether a component is permanent focus owner.
|
* Specifies a callback that is invoked to check whether a component is permanent focus owner.
|
||||||
* Used to paint focus indicators.
|
* Used to paint focus indicators.
|
||||||
@@ -461,7 +472,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 +492,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 +518,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 +550,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 +566,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 +582,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 +598,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 +614,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 +626,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 +638,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 +647,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}
|
||||||
*
|
*
|
||||||
@@ -1176,12 +1211,15 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies whether all text is selected when the text component gains focus.
|
* Specifies whether all text is selected when the text component gains focus.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses),
|
||||||
|
* {@link javax.swing.JComboBox} (since 3.6) and {@link javax.swing.JSpinner} (since 3.6)<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
* <strong>Allowed Values</strong>
|
* <strong>Allowed Values</strong>
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
|
||||||
|
*
|
||||||
|
* @see #SELECT_ALL_ON_MOUSE_CLICK
|
||||||
*/
|
*/
|
||||||
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
|
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
|
||||||
|
|
||||||
@@ -1196,6 +1234,12 @@ public interface FlatClientProperties
|
|||||||
* Select all text when the text component gains focus for the first time
|
* Select all text when the text component gains focus for the first time
|
||||||
* and selection was not modified (is at end of text).
|
* and selection was not modified (is at end of text).
|
||||||
* This is the default.
|
* This is the default.
|
||||||
|
* <p>
|
||||||
|
* <b>Limitations:</b>
|
||||||
|
* For {@link JFormattedTextField} and {@link JSpinner} this behaves
|
||||||
|
* as {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}.
|
||||||
|
* This is because of special behavior of {@link JFormattedTextField}
|
||||||
|
* that did not allow implementation of {@code "once"}.
|
||||||
*
|
*
|
||||||
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||||
*/
|
*/
|
||||||
@@ -1208,6 +1252,19 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
|
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether all text is selected when when clicking with the mouse
|
||||||
|
* into the text field (and if "select all on focus" policy is enabled).
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses),
|
||||||
|
* {@link javax.swing.JComboBox} and {@link javax.swing.JSpinner}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
String SELECT_ALL_ON_MOUSE_CLICK = "JTextField.selectAllOnMouseClick";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Placeholder text that is only painted if the text field is empty.
|
* Placeholder text that is only painted if the text field is empty.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -1386,13 +1443,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.
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -36,6 +37,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -43,6 +45,7 @@ import java.util.MissingResourceException;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.IntUnaryOperator;
|
import java.util.function.IntUnaryOperator;
|
||||||
@@ -99,6 +102,8 @@ public abstract class FlatLaf
|
|||||||
private static Map<String, String> globalExtraDefaults;
|
private static Map<String, String> globalExtraDefaults;
|
||||||
private Map<String, String> extraDefaults;
|
private Map<String, String> extraDefaults;
|
||||||
private static Function<String, Color> systemColorGetter;
|
private static Function<String, Color> systemColorGetter;
|
||||||
|
private static Set<String> uiKeyPlatformPrefixes;
|
||||||
|
private static Set<String> uiKeySpecialPrefixes;
|
||||||
|
|
||||||
private String desktopPropertyName;
|
private String desktopPropertyName;
|
||||||
private String desktopPropertyName2;
|
private String desktopPropertyName2;
|
||||||
@@ -110,6 +115,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 +125,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 +310,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 +406,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;
|
||||||
@@ -469,10 +525,10 @@ public abstract class FlatLaf
|
|||||||
|
|
||||||
// load defaults from properties
|
// load defaults from properties
|
||||||
List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading();
|
List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading();
|
||||||
if( lafClassesForDefaultsLoading != null )
|
if( lafClassesForDefaultsLoading == null )
|
||||||
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), isDark(), defaults );
|
lafClassesForDefaultsLoading = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() );
|
||||||
else
|
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons,
|
||||||
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults );
|
this::applyAdditionalProperties, getAdditionalDefaults(), isDark(), defaults );
|
||||||
|
|
||||||
// setup default font after loading defaults from properties
|
// setup default font after loading defaults from properties
|
||||||
// to allow defining "defaultFont" in properties
|
// to allow defining "defaultFont" in properties
|
||||||
@@ -489,9 +545,6 @@ public abstract class FlatLaf
|
|||||||
// initialize text antialiasing
|
// initialize text antialiasing
|
||||||
putAATextInfo( defaults );
|
putAATextInfo( defaults );
|
||||||
|
|
||||||
// apply additional defaults (e.g. from IntelliJ themes)
|
|
||||||
applyAdditionalDefaults( defaults );
|
|
||||||
|
|
||||||
// allow addons modifying UI defaults
|
// allow addons modifying UI defaults
|
||||||
for( FlatDefaultsAddon addon : addons )
|
for( FlatDefaultsAddon addon : addons )
|
||||||
addon.afterDefaultsLoading( this, defaults );
|
addon.afterDefaultsLoading( this, defaults );
|
||||||
@@ -501,6 +554,9 @@ public abstract class FlatLaf
|
|||||||
return UIScale.getUserScaleFactor();
|
return UIScale.getUserScaleFactor();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// add lazy UI delegate class loading (if necessary)
|
||||||
|
addLazyUIdelegateClassLoading( defaults );
|
||||||
|
|
||||||
if( postInitialization != null ) {
|
if( postInitialization != null ) {
|
||||||
postInitialization.accept( defaults );
|
postInitialization.accept( defaults );
|
||||||
postInitialization = null;
|
postInitialization = null;
|
||||||
@@ -509,7 +565,8 @@ public abstract class FlatLaf
|
|||||||
return defaults;
|
return defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
// apply additional properties (e.g. from IntelliJ themes)
|
||||||
|
void applyAdditionalProperties( Properties properties ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Class<?>> getLafClassesForDefaultsLoading() {
|
protected List<Class<?>> getLafClassesForDefaultsLoading() {
|
||||||
@@ -698,6 +755,53 @@ public abstract class FlatLaf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle UI delegate classes if running in special application where multiple class loaders are involved.
|
||||||
|
* E.g. in Eclipse plugin or in LibreOffice extension.
|
||||||
|
* <p>
|
||||||
|
* Problem: Swing runs in Java's system classloader and FlatLaf is loaded in plugin classloader.
|
||||||
|
* When Swing tries to load UI delegate class in {@link UIDefaults#getUIClass(String, ClassLoader)},
|
||||||
|
* invoked from {@link UIDefaults#getUI(JComponent)}, it uses the component's classloader,
|
||||||
|
* which is Java's system classloader for core Swing components,
|
||||||
|
* and can not find FlatLaf UI delegates.
|
||||||
|
* <p>
|
||||||
|
* Solution: Add lazy values for UI delegate class names.
|
||||||
|
* Those lazy values use FlatLaf classloader to load UI delegate class.
|
||||||
|
* This is similar to what {@link UIDefaults#getUIClass(String, ClassLoader)} does.
|
||||||
|
* <p>
|
||||||
|
* Not using {@code defaults.put( "ClassLoader", FlatLaf.class.getClassLoader() )},
|
||||||
|
* which would work for FlatLaf UI delegates, but it would break custom
|
||||||
|
* UI delegates used in other classloaders.
|
||||||
|
*/
|
||||||
|
private static void addLazyUIdelegateClassLoading( UIDefaults defaults ) {
|
||||||
|
if( FlatLaf.class.getClassLoader() == ClassLoader.getSystemClassLoader() )
|
||||||
|
return; // not necessary
|
||||||
|
|
||||||
|
Map<String, LazyValue> map = new HashMap<>();
|
||||||
|
for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
|
||||||
|
Object key = e.getKey();
|
||||||
|
Object value = e.getValue();
|
||||||
|
if( key instanceof String && ((String)key).endsWith( "UI" ) &&
|
||||||
|
value instanceof String && !defaults.containsKey( value ) )
|
||||||
|
{
|
||||||
|
String className = (String) value;
|
||||||
|
map.put( className, (LazyValue) t -> {
|
||||||
|
try {
|
||||||
|
Class<?> uiClass = FlatLaf.class.getClassLoader().loadClass( className );
|
||||||
|
if( ComponentUI.class.isAssignableFrom( uiClass ) )
|
||||||
|
return uiClass;
|
||||||
|
} catch( ClassNotFoundException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// let UIDefaults.getUIClass() try to load UI delegate class
|
||||||
|
return null;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defaults.putAll( map );
|
||||||
|
}
|
||||||
|
|
||||||
private void putAATextInfo( UIDefaults defaults ) {
|
private void putAATextInfo( UIDefaults defaults ) {
|
||||||
if ( SystemInfo.isMacOS && SystemInfo.isJetBrainsJVM ) {
|
if ( SystemInfo.isMacOS && SystemInfo.isJetBrainsJVM ) {
|
||||||
// The awt.font.desktophints property suggests sub-pixel anti-aliasing
|
// The awt.font.desktophints property suggests sub-pixel anti-aliasing
|
||||||
@@ -1022,6 +1126,92 @@ public abstract class FlatLaf
|
|||||||
FlatLaf.systemColorGetter = systemColorGetter;
|
FlatLaf.systemColorGetter = systemColorGetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns UI key prefix, used in FlatLaf properties files, for light or dark themes.
|
||||||
|
* Return value is either {@code [light]} or {@code [dark]}.
|
||||||
|
*
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
public static String getUIKeyLightOrDarkPrefix( boolean dark ) {
|
||||||
|
return dark ? "[dark]" : "[light]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns set of UI key prefixes, used in FlatLaf properties files, for current platform.
|
||||||
|
* If UI keys in properties files start with a prefix (e.g. {@code [someprefix]Button.background}),
|
||||||
|
* then they are only used if that prefix is contained in this set
|
||||||
|
* (or is one of {@code [light]} or {@code [dark]} depending on current theme).
|
||||||
|
* <p>
|
||||||
|
* By default, the set contains one or more of following prefixes:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code [win]} on Windows
|
||||||
|
* <li>{@code [mac]} on macOS
|
||||||
|
* <li>{@code [linux]} on Linux
|
||||||
|
* <li>{@code [unknown]} on other platforms
|
||||||
|
* <li>{@code [gnome]} on Linux with GNOME desktop environment
|
||||||
|
* <li>{@code [kde]} on Linux with KDE desktop environment
|
||||||
|
* <li>on Linux, the value of the environment variable {@code XDG_CURRENT_DESKTOP},
|
||||||
|
* split at colons and converted to lower case (e.g. if value of {@code XDG_CURRENT_DESKTOP}
|
||||||
|
* is {@code ubuntu:GNOME}, then {@code [ubuntu]} and {@code [gnome]})
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* You can add own prefixes to the set.
|
||||||
|
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
|
||||||
|
*
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
public static Set<String> getUIKeyPlatformPrefixes() {
|
||||||
|
if( uiKeyPlatformPrefixes == null ) {
|
||||||
|
uiKeyPlatformPrefixes = new HashSet<>();
|
||||||
|
uiKeyPlatformPrefixes.add(
|
||||||
|
SystemInfo.isWindows ? "[win]" :
|
||||||
|
SystemInfo.isMacOS ? "[mac]" :
|
||||||
|
SystemInfo.isLinux ? "[linux]" : "[unknown]" );
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
if( SystemInfo.isLinux ) {
|
||||||
|
if( SystemInfo.isGNOME )
|
||||||
|
uiKeyPlatformPrefixes.add( "[gnome]" );
|
||||||
|
else if( SystemInfo.isKDE )
|
||||||
|
uiKeyPlatformPrefixes.add( "[kde]" );
|
||||||
|
|
||||||
|
// add values from XDG_CURRENT_DESKTOP for other desktops
|
||||||
|
String desktop = System.getenv( "XDG_CURRENT_DESKTOP" );
|
||||||
|
if( desktop != null ) {
|
||||||
|
// XDG_CURRENT_DESKTOP is a colon-separated list of strings
|
||||||
|
// https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-onlyshowin
|
||||||
|
// e.g. "ubuntu:GNOME" on Ubuntu 24.10 or "GNOME-Classic:GNOME" on CentOS 7
|
||||||
|
for( String desk : StringUtils.split( desktop.toLowerCase( Locale.ENGLISH ), ':', true, true ) )
|
||||||
|
uiKeyPlatformPrefixes.add( '[' + desk + ']' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uiKeyPlatformPrefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns set of special UI key prefixes, used in FlatLaf properties files.
|
||||||
|
* Unlike other prefixes, properties with special prefixes are preserved.
|
||||||
|
* You can access them using `UIManager`. E.g. `UIManager.get( "[someSpecialPrefix]someKey" )`.
|
||||||
|
* <p>
|
||||||
|
* By default, the set contains following special prefixes:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code [style]}
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* You can add own prefixes to the set.
|
||||||
|
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
|
||||||
|
*
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
public static Set<String> getUIKeySpecialPrefixes() {
|
||||||
|
if( uiKeySpecialPrefixes == null ) {
|
||||||
|
uiKeySpecialPrefixes = new HashSet<>();
|
||||||
|
uiKeySpecialPrefixes.add( "[style]" );
|
||||||
|
}
|
||||||
|
return uiKeySpecialPrefixes;
|
||||||
|
}
|
||||||
|
|
||||||
private static void reSetLookAndFeel() {
|
private static void reSetLookAndFeel() {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -204,6 +216,16 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether safe triangle is used to improve usability of submenus.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.5.1
|
||||||
|
*/
|
||||||
|
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a system property is set and returns {@code true} if its value
|
* Checks whether a system property is set and returns {@code true} if its value
|
||||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@@ -25,20 +24,16 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import javax.swing.UIDefaults;
|
|
||||||
import javax.swing.plaf.ColorUIResource;
|
|
||||||
import com.formdev.flatlaf.json.Json;
|
import com.formdev.flatlaf.json.Json;
|
||||||
import com.formdev.flatlaf.json.ParseException;
|
import com.formdev.flatlaf.json.ParseException;
|
||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
@@ -63,13 +58,11 @@ public class IntelliJTheme
|
|||||||
public final boolean dark;
|
public final boolean dark;
|
||||||
public final String author;
|
public final String author;
|
||||||
|
|
||||||
private final boolean isMaterialUILite;
|
private Map<String, String> jsonColors;
|
||||||
|
private Map<String, Object> jsonUI;
|
||||||
|
private Map<String, Object> jsonIcons;
|
||||||
|
|
||||||
private Map<String, String> colors;
|
private Map<String, String> namedColors = Collections.emptyMap();
|
||||||
private Map<String, Object> ui;
|
|
||||||
private Map<String, Object> icons;
|
|
||||||
|
|
||||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a IntelliJ .theme.json file from the given input stream,
|
* Loads a IntelliJ .theme.json file from the given input stream,
|
||||||
@@ -84,7 +77,7 @@ public class IntelliJTheme
|
|||||||
try {
|
try {
|
||||||
return FlatLaf.setup( createLaf( in ) );
|
return FlatLaf.setup( createLaf( in ) );
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,94 +131,90 @@ public class IntelliJTheme
|
|||||||
dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
|
dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
|
||||||
author = (String) json.get( "author" );
|
author = (String) json.get( "author" );
|
||||||
|
|
||||||
isMaterialUILite = author.equals( "Mallowigi" );
|
jsonColors = (Map<String, String>) json.get( "colors" );
|
||||||
|
jsonUI = (Map<String, Object>) json.get( "ui" );
|
||||||
colors = (Map<String, String>) json.get( "colors" );
|
jsonIcons = (Map<String, Object>) json.get( "icons" );
|
||||||
ui = (Map<String, Object>) json.get( "ui" );
|
|
||||||
icons = (Map<String, Object>) json.get( "icons" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyProperties( UIDefaults defaults ) {
|
private void applyProperties( Properties properties ) {
|
||||||
if( ui == null )
|
if( jsonUI == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
defaults.put( "Component.isIntelliJTheme", true );
|
put( properties, "Component.isIntelliJTheme", "true" );
|
||||||
|
|
||||||
// enable button shadows
|
// enable button shadows
|
||||||
defaults.put( "Button.paintShadow", true );
|
put( properties, "Button.paintShadow", "true" );
|
||||||
defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
|
put( properties, "Button.shadowWidth", dark ? "2" : "1" );
|
||||||
|
|
||||||
Map<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
|
Map<String, String> themeSpecificProps = removeThemeSpecificProps( properties );
|
||||||
|
Set<String> jsonUIKeys = new HashSet<>();
|
||||||
|
|
||||||
loadNamedColors( defaults );
|
// Json node "colors"
|
||||||
|
loadNamedColors( properties, jsonUIKeys );
|
||||||
|
|
||||||
// convert Json "ui" structure to UI defaults
|
// convert Json "ui" structure to UI properties
|
||||||
ArrayList<Object> defaultsKeysCache = new ArrayList<>();
|
for( Map.Entry<String, Object> e : jsonUI.entrySet() )
|
||||||
Set<String> uiKeys = new HashSet<>();
|
apply( e.getKey(), e.getValue(), properties, jsonUIKeys );
|
||||||
for( Map.Entry<String, Object> e : ui.entrySet() )
|
|
||||||
apply( e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
|
||||||
|
|
||||||
applyColorPalette( defaults );
|
// set FlatLaf variables
|
||||||
applyCheckBoxColors( defaults );
|
copyIfSetInJson( properties, jsonUIKeys, "@background", "Panel.background", "*.background" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@foreground", "CheckBox.foreground", "*.foreground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@accentBaseColor",
|
||||||
|
"ColorPalette.accent", // Material UI Lite, Hiberbee
|
||||||
|
"ColorPalette.accentColor", // Dracula, One Dark
|
||||||
|
"ProgressBar.foreground",
|
||||||
|
"*.selectionBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@accentUnderlineColor", "*.underlineColor", "TabbedPane.underlineColor" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionBackground", "*.selectionBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionForeground", "*.selectionForeground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveBackground", "*.selectionInactiveBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveForeground", "*.selectionInactiveForeground" );
|
||||||
|
|
||||||
|
// Json node "icons/ColorPalette"
|
||||||
|
applyIconsColorPalette( properties );
|
||||||
|
|
||||||
|
// apply "CheckBox.icon." colors
|
||||||
|
applyCheckBoxColors( properties );
|
||||||
|
|
||||||
// copy values
|
// copy values
|
||||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||||
Object value = defaults.get( e.getValue() );
|
Object value = properties.get( e.getValue() );
|
||||||
if( value != null )
|
if( value != null )
|
||||||
defaults.put( e.getKey(), value );
|
put( properties, e.getKey(), value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||||
Object panelBackground = defaults.get( "Panel.background" );
|
put( properties, "Button.disabledBackground", "@disabledBackground" );
|
||||||
defaults.put( "Button.disabledBackground", panelBackground );
|
put( properties, "ToggleButton.disabledBackground", "@disabledBackground" );
|
||||||
defaults.put( "ToggleButton.disabledBackground", panelBackground );
|
|
||||||
|
|
||||||
// fix Button borders
|
// fix Button
|
||||||
copyIfNotSet( defaults, "Button.focusedBorderColor", "Component.focusedBorderColor", uiKeys );
|
fixStartEnd( properties, jsonUIKeys, "Button.startBackground", "Button.endBackground", "Button.background" );
|
||||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
fixStartEnd( properties, jsonUIKeys, "Button.startBorderColor", "Button.endBorderColor", "Button.borderColor" );
|
||||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
fixStartEnd( properties, jsonUIKeys, "Button.default.startBackground", "Button.default.endBackground", "Button.default.background" );
|
||||||
|
fixStartEnd( properties, jsonUIKeys, "Button.default.startBorderColor", "Button.default.endBorderColor", "Button.default.borderColor" );
|
||||||
// IDEA uses an SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
|
||||||
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
|
||||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
|
||||||
if( helpButtonBackground == null )
|
|
||||||
helpButtonBackground = defaults.get( "Button.background" );
|
|
||||||
if( helpButtonBorderColor == null )
|
|
||||||
helpButtonBorderColor = defaults.get( "Button.borderColor" );
|
|
||||||
defaults.put( "HelpButton.background", helpButtonBackground );
|
|
||||||
defaults.put( "HelpButton.borderColor", helpButtonBorderColor );
|
|
||||||
defaults.put( "HelpButton.disabledBackground", panelBackground );
|
|
||||||
defaults.put( "HelpButton.disabledBorderColor", defaults.get( "Button.disabledBorderColor" ) );
|
|
||||||
defaults.put( "HelpButton.focusedBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
|
||||||
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
|
||||||
|
|
||||||
// IDEA uses TextField.background for editable ComboBox and Spinner
|
// IDEA uses TextField.background for editable ComboBox and Spinner
|
||||||
Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" );
|
Object textFieldBackground = get( properties, themeSpecificProps, "TextField.background" );
|
||||||
defaults.put( "ComboBox.editableBackground", textFieldBackground );
|
put( properties, "ComboBox.editableBackground", textFieldBackground );
|
||||||
defaults.put( "Spinner.background", textFieldBackground );
|
put( properties, "Spinner.background", textFieldBackground );
|
||||||
|
|
||||||
// Spinner arrow button always has same colors as ComboBox arrow button
|
|
||||||
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
|
||||||
defaults.put( "Spinner.buttonArrowColor", defaults.get( "ComboBox.buttonArrowColor" ) );
|
|
||||||
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
|
||||||
|
|
||||||
// some themes specify colors for TextField.background, but forget to specify it for other components
|
// some themes specify colors for TextField.background, but forget to specify it for other components
|
||||||
// (probably because those components are not used in IntelliJ IDEA)
|
// (probably because those components are not used in IntelliJ IDEA)
|
||||||
putAll( defaults, textFieldBackground,
|
putAll( properties, textFieldBackground,
|
||||||
"EditorPane.background",
|
"EditorPane.background",
|
||||||
"FormattedTextField.background",
|
"FormattedTextField.background",
|
||||||
"PasswordField.background",
|
"PasswordField.background",
|
||||||
"TextArea.background",
|
"TextArea.background",
|
||||||
"TextPane.background"
|
"TextPane.background"
|
||||||
);
|
);
|
||||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ),
|
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionBackground" ),
|
||||||
"EditorPane.selectionBackground",
|
"EditorPane.selectionBackground",
|
||||||
"FormattedTextField.selectionBackground",
|
"FormattedTextField.selectionBackground",
|
||||||
"PasswordField.selectionBackground",
|
"PasswordField.selectionBackground",
|
||||||
"TextArea.selectionBackground",
|
"TextArea.selectionBackground",
|
||||||
"TextPane.selectionBackground"
|
"TextPane.selectionBackground"
|
||||||
);
|
);
|
||||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ),
|
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionForeground" ),
|
||||||
"EditorPane.selectionForeground",
|
"EditorPane.selectionForeground",
|
||||||
"FormattedTextField.selectionForeground",
|
"FormattedTextField.selectionForeground",
|
||||||
"PasswordField.selectionForeground",
|
"PasswordField.selectionForeground",
|
||||||
@@ -235,7 +224,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
||||||
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
||||||
putAll( defaults, panelBackground,
|
putAll( properties, "@disabledBackground",
|
||||||
"ComboBox.disabledBackground",
|
"ComboBox.disabledBackground",
|
||||||
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
||||||
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
||||||
@@ -246,132 +235,148 @@ public class IntelliJTheme
|
|||||||
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
||||||
);
|
);
|
||||||
|
|
||||||
// fix ToggleButton
|
|
||||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
|
||||||
defaults.put( "ToggleButton.startBackground", defaults.get( "Button.startBackground" ) );
|
|
||||||
if( !uiKeys.contains( "ToggleButton.endBackground" ) && !uiKeys.contains( "*.endBackground" ) )
|
|
||||||
defaults.put( "ToggleButton.endBackground", defaults.get( "Button.endBackground" ) );
|
|
||||||
if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) )
|
|
||||||
defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) );
|
|
||||||
|
|
||||||
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
|
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
|
||||||
Color desktopBackgroundBase = defaults.getColor( "Panel.background" );
|
put( properties, "Desktop.background", dark ? "lighten($Panel.background,5%)" : "darken($Panel.background,5%)" );
|
||||||
Color desktopBackground = ColorFunctions.applyFunctions( desktopBackgroundBase,
|
|
||||||
new ColorFunctions.HSLIncreaseDecrease( 2, dark, 5, false, true ) );
|
|
||||||
defaults.put( "Desktop.background", new ColorUIResource( desktopBackground ) );
|
|
||||||
|
|
||||||
// fix List and Table background colors in Material UI Lite themes
|
|
||||||
if( isMaterialUILite ) {
|
|
||||||
defaults.put( "List.background", defaults.get( "Tree.background" ) );
|
|
||||||
defaults.put( "Table.background", defaults.get( "Tree.background" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// limit tree row height
|
// limit tree row height
|
||||||
int rowHeight = defaults.getInt( "Tree.rowHeight" );
|
String rowHeightStr = (String) properties.get( "Tree.rowHeight" );
|
||||||
|
int rowHeight = (rowHeightStr != null) ? Integer.parseInt( rowHeightStr ) : 0;
|
||||||
if( rowHeight > 22 )
|
if( rowHeight > 22 )
|
||||||
defaults.put( "Tree.rowHeight", 22 );
|
put( properties, "Tree.rowHeight", "22" );
|
||||||
|
|
||||||
// get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix
|
// get (and remove) theme specific wildcard replacements, which override all other properties that end with same suffix
|
||||||
HashMap<String, Object> wildcards = new HashMap<>();
|
HashMap<String, String> wildcardProps = new HashMap<>();
|
||||||
Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
|
Iterator<Map.Entry<String, String>> it = themeSpecificProps.entrySet().iterator();
|
||||||
while( it.hasNext() ) {
|
while( it.hasNext() ) {
|
||||||
Entry<Object, Object> e = it.next();
|
Map.Entry<String, String> e = it.next();
|
||||||
String key = (String) e.getKey();
|
String key = e.getKey();
|
||||||
if( key.startsWith( "*." ) ) {
|
if( key.startsWith( "*." ) ) {
|
||||||
wildcards.put( key.substring( "*.".length() ), e.getValue() );
|
wildcardProps.put( key, e.getValue() );
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// override UI defaults with theme specific wildcard replacements
|
// override properties with theme specific wildcard replacements
|
||||||
if( !wildcards.isEmpty() ) {
|
if( !wildcardProps.isEmpty() ) {
|
||||||
for( Object key : defaults.keySet().toArray() ) {
|
for( Map.Entry<String, String> e : wildcardProps.entrySet() )
|
||||||
int dot;
|
applyWildcard( properties, e.getKey(), e.getValue() );
|
||||||
if( !(key instanceof String) ||
|
|
||||||
(dot = ((String)key).lastIndexOf( '.' )) < 0 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
String wildcardKey = ((String)key).substring( dot + 1 );
|
|
||||||
Object wildcardValue = wildcards.get( wildcardKey );
|
|
||||||
if( wildcardValue != null )
|
|
||||||
defaults.put( key, wildcardValue );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply theme specific UI defaults at the end to allow overwriting
|
// apply theme specific properties at the end to allow overwriting
|
||||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
for( Map.Entry<String, String> e : themeSpecificProps.entrySet() ) {
|
||||||
Object key = e.getKey();
|
String key = e.getKey();
|
||||||
Object value = e.getValue();
|
String value = e.getValue();
|
||||||
|
|
||||||
// append styles to existing styles
|
// append styles to existing styles
|
||||||
if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
|
if( key.startsWith( "[style]" ) ) {
|
||||||
Object oldValue = defaults.get( key );
|
String oldValue = (String) properties.get( key );
|
||||||
if( oldValue != null )
|
if( oldValue != null )
|
||||||
value = oldValue + "; " + value;
|
value = oldValue + "; " + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults.put( key, value );
|
put( properties, key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// let Java release memory
|
// let Java release memory
|
||||||
colors = null;
|
jsonColors = null;
|
||||||
ui = null;
|
jsonUI = null;
|
||||||
icons = null;
|
jsonIcons = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object get( UIDefaults defaults, Map<Object, Object> themeSpecificDefaults, String key ) {
|
private String get( Properties properties, Map<String, String> themeSpecificProps, String key ) {
|
||||||
return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
|
return themeSpecificProps.getOrDefault( key, (String) properties.get( key ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putAll( UIDefaults defaults, Object value, String... keys ) {
|
private void put( Properties properties, Object key, Object value ) {
|
||||||
|
if( value != null )
|
||||||
|
properties.put( key, value );
|
||||||
|
else
|
||||||
|
properties.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putAll( Properties properties, Object value, String... keys ) {
|
||||||
for( String key : keys )
|
for( String key : keys )
|
||||||
defaults.put( key, value );
|
put( properties, key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
private void copyIfSetInJson( Properties properties, Set<String> jsonUIKeys, String destKey, String... srcKeys ) {
|
||||||
// search for theme specific UI defaults keys
|
for( String srcKey : srcKeys ) {
|
||||||
|
if( jsonUIKeys.contains( srcKey ) ) {
|
||||||
|
Object value = properties.get( srcKey );
|
||||||
|
if( value != null ) {
|
||||||
|
put( properties, destKey, value );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixStartEnd( Properties properties, Set<String> jsonUIKeys, String startKey, String endKey, String key ) {
|
||||||
|
if( jsonUIKeys.contains( startKey ) && jsonUIKeys.contains( endKey ) )
|
||||||
|
put( properties, key, "$" + startKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> removeThemeSpecificProps( Properties properties ) {
|
||||||
|
// search for theme specific properties keys
|
||||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||||
for( Object key : defaults.keySet() ) {
|
for( Object key : properties.keySet() ) {
|
||||||
if( key instanceof String && ((String)key).startsWith( "[" ) && !((String)key).startsWith( "[style]" ) )
|
if( ((String)key).startsWith( "{" ) )
|
||||||
themeSpecificKeys.add( (String) key );
|
themeSpecificKeys.add( (String) key );
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove theme specific UI defaults and remember only those for current theme
|
// special prefixes (priority from highest to lowest)
|
||||||
Map<Object, Object> themeSpecificDefaults = new HashMap<>();
|
String currentThemePrefix = '{' + name.replace( ' ', '_' ) + '}';
|
||||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
String currentThemeAndAuthorPrefix = '{' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + '}';
|
||||||
String currentThemeAndAuthorPrefix = '[' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + ']';
|
String currentAuthorPrefix = "{author-" + author.replace( ' ', '_' ) + '}';
|
||||||
String currentAuthorPrefix = "[author-" + author.replace( ' ', '_' ) + ']';
|
String lightOrDarkPrefix = dark ? "{*-dark}" : "{*-light}";
|
||||||
String allThemesPrefix = "[*]";
|
String allThemesPrefix = "{*}";
|
||||||
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix };
|
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, lightOrDarkPrefix, allThemesPrefix };
|
||||||
|
|
||||||
|
// collect values for special prefixes in its own maps
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
Map<String, String>[] maps = new Map[prefixes.length];
|
||||||
|
for( int i = 0; i < maps.length; i++ )
|
||||||
|
maps[i] = new HashMap<>();
|
||||||
|
|
||||||
|
// remove theme specific properties and remember only those for current theme
|
||||||
for( String key : themeSpecificKeys ) {
|
for( String key : themeSpecificKeys ) {
|
||||||
Object value = defaults.remove( key );
|
String value = (String) properties.remove( key );
|
||||||
for( String prefix : prefixes ) {
|
for( int i = 0; i < prefixes.length; i++ ) {
|
||||||
|
String prefix = prefixes[i];
|
||||||
if( key.startsWith( prefix ) ) {
|
if( key.startsWith( prefix ) ) {
|
||||||
themeSpecificDefaults.put( key.substring( prefix.length() ), value );
|
maps[i].put( key.substring( prefix.length() ), value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return themeSpecificDefaults;
|
// copy values into single map (from lowest to highest priority)
|
||||||
|
Map<String, String> themeSpecificProps = new HashMap<>();
|
||||||
|
for( int i = maps.length - 1; i >= 0; i-- )
|
||||||
|
themeSpecificProps.putAll( maps[i] );
|
||||||
|
return themeSpecificProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors
|
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors
|
||||||
*/
|
*/
|
||||||
private void loadNamedColors( UIDefaults defaults ) {
|
private void loadNamedColors( Properties properties, Set<String> jsonUIKeys ) {
|
||||||
if( colors == null )
|
if( jsonColors == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
namedColors = new HashMap<>();
|
namedColors = new HashMap<>();
|
||||||
|
|
||||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
for( Map.Entry<String, String> e : jsonColors.entrySet() ) {
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
ColorUIResource color = parseColor( value );
|
if( canParseColor( value ) ) {
|
||||||
if( color != null ) {
|
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
namedColors.put( key, color );
|
namedColors.put( key, value );
|
||||||
defaults.put( "ColorPalette." + key, color );
|
|
||||||
|
String uiKey = "ColorPalette." + key;
|
||||||
|
put( properties, uiKey, value );
|
||||||
|
|
||||||
|
// this is only necessary for copyIfSetInJson() (used for accent color)
|
||||||
|
jsonUIKeys.add( uiKey );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,7 +385,7 @@ public class IntelliJTheme
|
|||||||
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors
|
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
private void apply( String key, Object value, Properties properties, Set<String> jsonUIKeys ) {
|
||||||
if( value instanceof Map ) {
|
if( value instanceof Map ) {
|
||||||
Map<String, Object> map = (Map<String, Object>)value;
|
Map<String, Object> map = (Map<String, Object>)value;
|
||||||
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
||||||
@@ -388,12 +393,12 @@ public class IntelliJTheme
|
|||||||
: SystemInfo.isMacOS ? "os.mac"
|
: SystemInfo.isMacOS ? "os.mac"
|
||||||
: SystemInfo.isLinux ? "os.linux" : null;
|
: SystemInfo.isLinux ? "os.linux" : null;
|
||||||
if( osKey != null && map.containsKey( osKey ) )
|
if( osKey != null && map.containsKey( osKey ) )
|
||||||
apply( key, map.get( osKey ), defaults, defaultsKeysCache, uiKeys );
|
apply( key, map.get( osKey ), properties, jsonUIKeys );
|
||||||
else if( map.containsKey( "os.default" ) )
|
else if( map.containsKey( "os.default" ) )
|
||||||
apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys );
|
apply( key, map.get( "os.default" ), properties, jsonUIKeys );
|
||||||
} else {
|
} else {
|
||||||
for( Map.Entry<String, Object> e : map.entrySet() )
|
for( Map.Entry<String, Object> e : map.entrySet() )
|
||||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
apply( key + '.' + e.getKey(), e.getValue(), properties, jsonUIKeys );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( "".equals( value ) )
|
if( "".equals( value ) )
|
||||||
@@ -408,25 +413,40 @@ public class IntelliJTheme
|
|||||||
key.equals( "Tree.rightChildIndent" ) )
|
key.equals( "Tree.rightChildIndent" ) )
|
||||||
return; // ignore
|
return; // ignore
|
||||||
|
|
||||||
|
// ignore icons
|
||||||
|
if( key.endsWith( "Icon" ) )
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
// map keys
|
// map keys
|
||||||
key = uiKeyMapping.getOrDefault( key, key );
|
key = uiKeyMapping.getOrDefault( key, key );
|
||||||
if( key.isEmpty() )
|
if( key.isEmpty() )
|
||||||
return; // ignore key
|
return; // ignore key
|
||||||
|
|
||||||
// exclude properties
|
// exclude properties (1st level)
|
||||||
int dot = key.indexOf( '.' );
|
int dot = key.indexOf( '.' );
|
||||||
if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) )
|
if( dot > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot + 1 ) ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) )
|
// exclude properties (2st level)
|
||||||
|
int dot2 = (dot > 0) ? key.indexOf( '.', dot + 1 ) : -1;
|
||||||
|
if( dot2 > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot2 + 1 ) ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uiKeys.add( key );
|
// exclude properties (contains)
|
||||||
|
for( String s : uiKeyExcludesContains ) {
|
||||||
|
if( key.contains( s ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String valueStr = value.toString();
|
if( uiKeyDoNotOverride.contains( key ) && jsonUIKeys.contains( key ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
jsonUIKeys.add( key );
|
||||||
|
|
||||||
|
String valueStr = value.toString().trim();
|
||||||
|
|
||||||
// map named colors
|
// map named colors
|
||||||
Object uiValue = namedColors.get( valueStr );
|
String uiValue = namedColors.get( valueStr );
|
||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
if( uiValue == null ) {
|
if( uiValue == null ) {
|
||||||
@@ -445,47 +465,64 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
try {
|
try {
|
||||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
|
UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||||
|
uiValue = valueStr;
|
||||||
} catch( RuntimeException ex ) {
|
} catch( RuntimeException ex ) {
|
||||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
UIDefaultsLoader.logParseError( key, valueStr, ex, true );
|
||||||
return; // ignore invalid value
|
return; // ignore invalid value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( key.startsWith( "*." ) ) {
|
// wildcards
|
||||||
// wildcard
|
if( applyWildcard( properties, key, uiValue ) )
|
||||||
String tail = key.substring( 1 );
|
return;
|
||||||
|
|
||||||
// because we can not iterate over the UI defaults keys while
|
put( properties, key, uiValue );
|
||||||
// modifying UI defaults in the same loop, we have to copy the keys
|
|
||||||
if( defaultsKeysCache.size() != defaults.size() ) {
|
|
||||||
defaultsKeysCache.clear();
|
|
||||||
Enumeration<Object> e = defaults.keys();
|
|
||||||
while( e.hasMoreElements() )
|
|
||||||
defaultsKeysCache.add( e.nextElement() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace all values in UI defaults that match the wildcard key
|
|
||||||
for( Object k : defaultsKeysCache ) {
|
|
||||||
if( k.equals( "Desktop.background" ) ||
|
|
||||||
k.equals( "DesktopIcon.background" ) ||
|
|
||||||
k.equals( "TabbedPane.focusColor" ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( k instanceof String ) {
|
|
||||||
// support replacing of mapped keys
|
|
||||||
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
|
||||||
// because it is mapped from ComboBox.ArrowButton.background)
|
|
||||||
String km = uiKeyInverseMapping.getOrDefault( k, (String) k );
|
|
||||||
if( km.endsWith( tail ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
|
||||||
defaults.put( k, uiValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
defaults.put( key, uiValue );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean applyWildcard( Properties properties, String key, String value ) {
|
||||||
|
if( !key.startsWith( "*." ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String tail = key.substring( 1 );
|
||||||
|
|
||||||
|
// because we can not iterate over the properties keys while
|
||||||
|
// modifying properties in the same loop, we have to copy the keys
|
||||||
|
String[] keys = properties.keySet().toArray( new String[properties.size()] );
|
||||||
|
|
||||||
|
// replace all values in properties that match the wildcard key
|
||||||
|
for( String k : keys ) {
|
||||||
|
if( k.startsWith( "*" ) ||
|
||||||
|
k.startsWith( "@" ) ||
|
||||||
|
k.startsWith( "HelpButton." ) ||
|
||||||
|
k.startsWith( "JX" ) ||
|
||||||
|
k.startsWith( "Jide" ) ||
|
||||||
|
k.startsWith( "ProgressBar.selection" ) ||
|
||||||
|
k.startsWith( "TitlePane." ) ||
|
||||||
|
k.startsWith( "ToggleButton.tab." ) ||
|
||||||
|
k.equals( "Desktop.background" ) ||
|
||||||
|
k.equals( "DesktopIcon.background" ) ||
|
||||||
|
k.equals( "TabbedPane.focusColor" ) ||
|
||||||
|
k.endsWith( ".hoverBackground" ) ||
|
||||||
|
k.endsWith( ".pressedBackground" ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// support replacing of mapped keys
|
||||||
|
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
||||||
|
// because it is mapped from ComboBox.ArrowButton.background)
|
||||||
|
String km = uiKeyInverseMapping.getOrDefault( k, k );
|
||||||
|
if( km.endsWith( tail ) && !k.startsWith( "CheckBox.icon." ) )
|
||||||
|
put( properties, k, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: also add wildcards to properties and let UIDefaultsLoader
|
||||||
|
// process it on BasicLookAndFeel UI defaults
|
||||||
|
put( properties, key, value );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private String fixColorIfValid( String newColorStr, String colorStr ) {
|
private String fixColorIfValid( String newColorStr, String colorStr ) {
|
||||||
try {
|
try {
|
||||||
// check whether it is valid
|
// check whether it is valid
|
||||||
@@ -497,11 +534,11 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyColorPalette( UIDefaults defaults ) {
|
private void applyIconsColorPalette( Properties properties ) {
|
||||||
if( icons == null )
|
if( jsonIcons == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object palette = icons.get( "ColorPalette" );
|
Object palette = jsonIcons.get( "ColorPalette" );
|
||||||
if( !(palette instanceof Map) )
|
if( !(palette instanceof Map) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -510,44 +547,48 @@ public class IntelliJTheme
|
|||||||
for( Map.Entry<String, Object> e : colorPalette.entrySet() ) {
|
for( Map.Entry<String, Object> e : colorPalette.entrySet() ) {
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
Object value = e.getValue();
|
Object value = e.getValue();
|
||||||
if( key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
if( key.startsWith( "Checkbox." ) || key.startsWith( "#" ) || !(value instanceof String) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( dark )
|
if( dark )
|
||||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||||
|
|
||||||
ColorUIResource color = toColor( (String) value );
|
String color = toColor( (String) value );
|
||||||
if( color != null )
|
if( color != null )
|
||||||
defaults.put( key, color );
|
put( properties, key, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ColorUIResource toColor( String value ) {
|
private String toColor( String value ) {
|
||||||
|
if( value.startsWith( "##" ) )
|
||||||
|
value = fixColorIfValid( value.substring( 1 ), value );
|
||||||
|
|
||||||
// map named colors
|
// map named colors
|
||||||
ColorUIResource color = namedColors.get( value );
|
String color = namedColors.get( value );
|
||||||
|
|
||||||
// parse color
|
// parse color
|
||||||
return (color != null) ? color : parseColor( value );
|
return (color != null) ? color : (canParseColor( value ) ? value : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ColorUIResource parseColor( String value ) {
|
private boolean canParseColor( String value ) {
|
||||||
try {
|
try {
|
||||||
return UIDefaultsLoader.parseColor( value );
|
return UIDefaultsLoader.parseColor( value ) != null;
|
||||||
} catch( IllegalArgumentException ex ) {
|
} catch( IllegalArgumentException ex ) {
|
||||||
return null;
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to parse color: '" + value + '\'', ex );
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
||||||
* these two components are specified in "icons > ColorPalette".
|
* these two components are specified in "icons > ColorPalette".
|
||||||
* FlatLaf uses vector icons and expects colors for the two components in UI defaults.
|
* FlatLaf uses vector icons and expects colors for the two components in properties.
|
||||||
*/
|
*/
|
||||||
private void applyCheckBoxColors( UIDefaults defaults ) {
|
private void applyCheckBoxColors( Properties properties ) {
|
||||||
if( icons == null )
|
if( jsonIcons == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object palette = icons.get( "ColorPalette" );
|
Object palette = jsonIcons.get( "ColorPalette" );
|
||||||
if( !(palette instanceof Map) )
|
if( !(palette instanceof Map) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -569,9 +610,9 @@ public class IntelliJTheme
|
|||||||
if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
|
if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
|
||||||
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
|
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
|
||||||
|
|
||||||
ColorUIResource color = toColor( (String) value );
|
String color = toColor( (String) value );
|
||||||
if( color != null ) {
|
if( color != null ) {
|
||||||
defaults.put( newKey, color );
|
put( properties, newKey, color );
|
||||||
|
|
||||||
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
||||||
if( key2 != null ) {
|
if( key2 != null ) {
|
||||||
@@ -592,7 +633,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
String newKey2 = checkboxKeyMapping.get( key2 );
|
String newKey2 = checkboxKeyMapping.get( key2 );
|
||||||
if( newKey2 != null )
|
if( newKey2 != null )
|
||||||
defaults.put( newKey2, color );
|
put( properties, newKey2, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,13 +644,13 @@ public class IntelliJTheme
|
|||||||
// update hover, pressed and focused colors
|
// update hover, pressed and focused colors
|
||||||
if( checkboxModified ) {
|
if( checkboxModified ) {
|
||||||
// for non-filled checkbox/radiobutton used in dark themes
|
// for non-filled checkbox/radiobutton used in dark themes
|
||||||
defaults.remove( "CheckBox.icon.focusWidth" );
|
properties.remove( "CheckBox.icon.focusWidth" );
|
||||||
defaults.put( "CheckBox.icon.hoverBorderColor", defaults.get( "CheckBox.icon.focusedBorderColor" ) );
|
put( properties, "CheckBox.icon.hoverBorderColor", properties.get( "CheckBox.icon.focusedBorderColor" ) );
|
||||||
|
|
||||||
// for filled checkbox/radiobutton used in light themes
|
// for filled checkbox/radiobutton used in light themes
|
||||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
properties.remove( "CheckBox.icon[filled].focusWidth" );
|
||||||
defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
put( properties, "CheckBox.icon[filled].hoverBorderColor", properties.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
||||||
defaults.put( "CheckBox.icon[filled].focusedSelectedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) );
|
put( properties, "CheckBox.icon[filled].focusedSelectedBackground", properties.get( "CheckBox.icon[filled].selectedBackground" ) );
|
||||||
|
|
||||||
if( dark ) {
|
if( dark ) {
|
||||||
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
||||||
@@ -623,22 +664,16 @@ public class IntelliJTheme
|
|||||||
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
||||||
};
|
};
|
||||||
for( String key : focusedBorderColorKeys ) {
|
for( String key : focusedBorderColorKeys ) {
|
||||||
Color color = defaults.getColor( key );
|
Object color = properties.get( key );
|
||||||
if( color != null ) {
|
if( color != null )
|
||||||
defaults.put( key, new ColorUIResource( new Color(
|
put( properties, key, "fade(" + color + ", 65%)" );
|
||||||
(color.getRGB() & 0xffffff) | 0xa6000000, true ) ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyIfNotSet( UIDefaults defaults, String destKey, String srcKey, Set<String> uiKeys ) {
|
private static final Set<String> uiKeyExcludesStartsWith;
|
||||||
if( !uiKeys.contains( destKey ) )
|
private static final String[] uiKeyExcludesContains;
|
||||||
defaults.put( destKey, defaults.get( srcKey ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Set<String> uiKeyExcludes;
|
|
||||||
private static final Set<String> uiKeyDoNotOverride;
|
private static final Set<String> uiKeyDoNotOverride;
|
||||||
/** Rename UI default keys (key --> value). */
|
/** Rename UI default keys (key --> value). */
|
||||||
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||||
@@ -650,29 +685,30 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
// IntelliJ UI properties that are not used in FlatLaf
|
// IntelliJ UI properties that are not used in FlatLaf
|
||||||
uiKeyExcludes = new HashSet<>( Arrays.asList(
|
uiKeyExcludesStartsWith = new HashSet<>( Arrays.asList(
|
||||||
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||||
"AvailableMnemonic.",
|
"AvailableMnemonic.",
|
||||||
"BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
"Badge.", "Banner.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||||
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||||
"Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
|
"Canvas.", "CellEditor.", "Code.", "CodeWithMe.", "ColumnControlButton.", "CombinedDiff.", "ComboBoxButton.",
|
||||||
"CurrentMnemonic.", "Counter.",
|
"CompilationCharts.", "CompletionPopup.", "ComplexPopup.", "Content.", "ContextHelp.", "CurrentMnemonic.", "Counter.",
|
||||||
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
|
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.",
|
||||||
|
"DisclosureButton.", "DragAndDrop.",
|
||||||
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
||||||
"FileColor.", "FlameGraph.", "Focus.",
|
"FileColor.", "FindPopup.", "FlameGraph.", "Focus.",
|
||||||
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
||||||
"HeaderColor.", "HelpTooltip.", "Hg.",
|
"HeaderColor.", "HelpTooltip.", "Hg.",
|
||||||
"IconBadge.", "InformationHint.", "InplaceRefactoringPopup.",
|
"IconBadge.", "InformationHint.", "InlineBanner.", "InplaceRefactoringPopup.",
|
||||||
"Lesson.", "Link.", "LiveIndicator.",
|
"Lesson.", "LineProfiler.", "Link.", "LiveIndicator.",
|
||||||
"MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
"MainMenu.", "MainToolbar.", "MainWindow.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||||
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||||
"OnePixelDivider.", "OptionButton.", "Outline.",
|
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||||
"ParameterInfo.", "Plugins.", "ProgressIcon.", "PsiViewer.",
|
"ParameterInfo.", "PresentationAssistant.", "Plugins.", "Profiler.", "ProgressIcon.", "PsiViewer.",
|
||||||
"ReviewList.", "RunWidget.",
|
"Resizable.", "Review.", "ReviewList.", "RunToolbar.", "RunWidget.",
|
||||||
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
||||||
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
||||||
"StatusBar.",
|
"StatusBar.", "StripeToolbar.",
|
||||||
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
|
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.", "TrialWidget.",
|
||||||
"UIDesigner.", "UnattendedHostStatus.",
|
"UIDesigner.", "UnattendedHostStatus.",
|
||||||
"ValidationTooltip.", "VersionControl.",
|
"ValidationTooltip.", "VersionControl.",
|
||||||
"WelcomeScreen.",
|
"WelcomeScreen.",
|
||||||
@@ -683,11 +719,24 @@ public class IntelliJTheme
|
|||||||
// possible typos in .theme.json files
|
// possible typos in .theme.json files
|
||||||
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
|
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
|
||||||
) );
|
) );
|
||||||
|
uiKeyExcludesContains = new String[] {
|
||||||
|
".darcula."
|
||||||
|
};
|
||||||
|
|
||||||
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
||||||
"TabbedPane.selectedForeground"
|
"TabbedPane.selectedForeground"
|
||||||
) );
|
) );
|
||||||
|
|
||||||
|
// "*."
|
||||||
|
uiKeyMapping.put( "*.fontFace", "" ); // ignore (used in OnePauintxi themes)
|
||||||
|
uiKeyMapping.put( "*.fontSize", "" ); // ignore (used in OnePauintxi themes)
|
||||||
|
|
||||||
|
// Button
|
||||||
|
uiKeyMapping.put( "Button.minimumSize", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
|
// CheckBox.iconSize
|
||||||
|
uiKeyMapping.put( "CheckBox.iconSize", "" ); // ignore (used in Rider themes)
|
||||||
|
|
||||||
// ComboBox
|
// ComboBox
|
||||||
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
||||||
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
||||||
@@ -696,14 +745,17 @@ public class IntelliJTheme
|
|||||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
||||||
uiKeyCopying.put( "ComboBox.buttonSeparatorColor", "Component.borderColor" );
|
|
||||||
uiKeyCopying.put( "ComboBox.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
|
||||||
|
|
||||||
// Component
|
// Component
|
||||||
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
||||||
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
||||||
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
||||||
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
||||||
|
uiKeyMapping.put( "Component.inactiveSuccessFocusColor", "Component.success.borderColor" );
|
||||||
|
uiKeyMapping.put( "Component.successFocusColor", "Component.success.focusedBorderColor" );
|
||||||
|
|
||||||
|
// Label
|
||||||
|
uiKeyMapping.put( "Label.disabledForegroundColor", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
// Link
|
// Link
|
||||||
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
||||||
@@ -711,10 +763,7 @@ public class IntelliJTheme
|
|||||||
// Menu
|
// Menu
|
||||||
uiKeyMapping.put( "Menu.border", "Menu.margin" );
|
uiKeyMapping.put( "Menu.border", "Menu.margin" );
|
||||||
uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" );
|
uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" );
|
||||||
uiKeyCopying.put( "CheckBoxMenuItem.margin", "MenuItem.margin" );
|
|
||||||
uiKeyCopying.put( "RadioButtonMenuItem.margin", "MenuItem.margin" );
|
|
||||||
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
|
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
|
||||||
uiKeyCopying.put( "MenuItem.underlineSelectionColor", "TabbedPane.underlineColor" );
|
|
||||||
|
|
||||||
// IDEA uses List.selectionBackground also for menu selection
|
// IDEA uses List.selectionBackground also for menu selection
|
||||||
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
|
||||||
@@ -722,13 +771,14 @@ public class IntelliJTheme
|
|||||||
uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" );
|
||||||
uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" );
|
||||||
|
|
||||||
// ProgressBar
|
// ProgressBar: IDEA uses ProgressBar.trackColor and ProgressBar.progressColor
|
||||||
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
|
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
|
||||||
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
|
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
|
||||||
uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" );
|
uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" );
|
||||||
uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" );
|
uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" );
|
||||||
uiKeyCopying.put( "ProgressBar.selectionForeground", "ProgressBar.background" );
|
|
||||||
uiKeyCopying.put( "ProgressBar.selectionBackground", "ProgressBar.foreground" );
|
// RadioButton
|
||||||
|
uiKeyMapping.put( "RadioButton.iconSize", "" ); // ignore (used in Rider themes)
|
||||||
|
|
||||||
// ScrollBar
|
// ScrollBar
|
||||||
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
|
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
|
||||||
@@ -738,34 +788,30 @@ public class IntelliJTheme
|
|||||||
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
|
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
|
||||||
|
|
||||||
// Slider
|
// Slider
|
||||||
|
uiKeyMapping.put( "Slider.buttonColor", "Slider.thumbColor" );
|
||||||
|
uiKeyMapping.put( "Slider.buttonBorderColor", "" ); // ignore
|
||||||
|
uiKeyMapping.put( "Slider.thumb", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "Slider.track", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "Slider.trackDisabled", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
|
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
uiKeyCopying.put( "Slider.trackValueColor", "ProgressBar.foreground" );
|
|
||||||
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
|
|
||||||
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
|
|
||||||
|
|
||||||
// Spinner
|
|
||||||
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
|
|
||||||
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
|
||||||
|
|
||||||
// TabbedPane
|
// TabbedPane
|
||||||
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
|
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
|
||||||
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
|
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
|
||||||
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
|
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
|
||||||
|
uiKeyMapping.put( "TabbedPane.tabAreaInsets", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
|
// TableHeader
|
||||||
|
uiKeyMapping.put( "TableHeader.cellBorder", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "TableHeader.height", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
// TitlePane
|
// TitlePane
|
||||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
|
||||||
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
||||||
uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" );
|
uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" );
|
||||||
|
|
||||||
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
|
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
|
||||||
uiKeyInverseMapping.put( e.getValue(), e.getKey() );
|
uiKeyInverseMapping.put( e.getValue(), e.getKey() );
|
||||||
|
|
||||||
uiKeyCopying.put( "ToggleButton.tab.underlineColor", "TabbedPane.underlineColor" );
|
|
||||||
uiKeyCopying.put( "ToggleButton.tab.disabledUnderlineColor", "TabbedPane.disabledUnderlineColor" );
|
|
||||||
uiKeyCopying.put( "ToggleButton.tab.selectedBackground", "TabbedPane.selectedBackground" );
|
|
||||||
uiKeyCopying.put( "ToggleButton.tab.hoverBackground", "TabbedPane.hoverColor" );
|
|
||||||
uiKeyCopying.put( "ToggleButton.tab.focusBackground", "TabbedPane.focusColor" );
|
|
||||||
|
|
||||||
checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" );
|
checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
|
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
|
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
|
||||||
@@ -818,17 +864,15 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
void applyAdditionalProperties( Properties properties ) {
|
||||||
theme.applyProperties( defaults );
|
theme.applyProperties( properties );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
ArrayList<Class<?>> lafClasses = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() );
|
||||||
lafClasses.add( FlatLaf.class );
|
lafClasses.add( 1, theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
||||||
lafClasses.add( theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
lafClasses.add( 2, theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
||||||
lafClasses.add( theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
|
||||||
lafClasses.add( ThemeLaf.class );
|
|
||||||
return lafClasses;
|
return lafClasses;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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 ) {
|
||||||
|
removeWindowListeners();
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Improves usability of submenus by using a
|
* Improves usability of submenus by using a
|
||||||
@@ -64,6 +65,7 @@ class SubMenuUsabilityHelper
|
|||||||
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
||||||
private static SubMenuUsabilityHelper instance;
|
private static SubMenuUsabilityHelper instance;
|
||||||
|
|
||||||
|
private boolean eventQueuePushNotSupported;
|
||||||
private SubMenuEventQueue subMenuEventQueue;
|
private SubMenuEventQueue subMenuEventQueue;
|
||||||
private SafeTrianglePainter safeTrianglePainter;
|
private SafeTrianglePainter safeTrianglePainter;
|
||||||
private boolean changePending;
|
private boolean changePending;
|
||||||
@@ -83,6 +85,9 @@ class SubMenuUsabilityHelper
|
|||||||
if( instance != null )
|
if( instance != null )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_SUB_MENU_SAFE_TRIANGLE, true ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
instance = new SubMenuUsabilityHelper();
|
instance = new SubMenuUsabilityHelper();
|
||||||
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
||||||
return true;
|
return true;
|
||||||
@@ -99,7 +104,7 @@ class SubMenuUsabilityHelper
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged( ChangeEvent e ) {
|
public void stateChanged( ChangeEvent e ) {
|
||||||
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
if( eventQueuePushNotSupported || !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// handle menu selection change later, but only once in case of temporary changes
|
// handle menu selection change later, but only once in case of temporary changes
|
||||||
@@ -173,8 +178,29 @@ debug*/
|
|||||||
targetBottomY = popupLocation.y + popupSize.height;
|
targetBottomY = popupLocation.y + popupSize.height;
|
||||||
|
|
||||||
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
||||||
if( subMenuEventQueue == null )
|
if( subMenuEventQueue == null ) {
|
||||||
subMenuEventQueue = new SubMenuEventQueue();
|
SubMenuEventQueue queue = new SubMenuEventQueue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||||
|
toolkit.getSystemEventQueue().push( queue );
|
||||||
|
|
||||||
|
// check whether push() worked
|
||||||
|
// (e.g. SWTSwing uses own event queue that does not support push())
|
||||||
|
if( toolkit.getSystemEventQueue() != queue ) {
|
||||||
|
eventQueuePushNotSupported = true;
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", null );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subMenuEventQueue = queue;
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
// catch runtime exception from EventQueue.push()
|
||||||
|
eventQueuePushNotSupported = true;
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", ex );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create safe triangle painter
|
// create safe triangle painter
|
||||||
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||||
@@ -247,8 +273,6 @@ debug*/
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
timeoutTimer.setRepeats( false );
|
timeoutTimer.setRepeats( false );
|
||||||
|
|
||||||
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninstall() {
|
void uninstall() {
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.UIDefaults;
|
import javax.swing.UIDefaults;
|
||||||
@@ -61,7 +63,6 @@ import com.formdev.flatlaf.util.HSLColor;
|
|||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SoftCache;
|
import com.formdev.flatlaf.util.SoftCache;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,15 +86,14 @@ class UIDefaultsLoader
|
|||||||
private static final String WILDCARD_PREFIX = "*.";
|
private static final String WILDCARD_PREFIX = "*.";
|
||||||
|
|
||||||
static final String KEY_VARIABLES = "FlatLaf.internal.variables";
|
static final String KEY_VARIABLES = "FlatLaf.internal.variables";
|
||||||
|
static final String KEY_PROPERTIES = "FlatLaf.internal.properties";
|
||||||
|
|
||||||
private static int parseColorDepth;
|
private static int parseColorDepth;
|
||||||
|
|
||||||
private static Map<String, ColorUIResource> systemColorCache;
|
private static Map<String, ColorUIResource> systemColorCache;
|
||||||
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
||||||
|
|
||||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
static ArrayList<Class<?>> getLafClassesForDefaultsLoading( Class<?> lookAndFeelClass ) {
|
||||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
|
||||||
{
|
|
||||||
// determine classes in class hierarchy in reverse order
|
// determine classes in class hierarchy in reverse order
|
||||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||||
for( Class<?> lafClass = lookAndFeelClass;
|
for( Class<?> lafClass = lookAndFeelClass;
|
||||||
@@ -102,20 +102,54 @@ class UIDefaultsLoader
|
|||||||
{
|
{
|
||||||
lafClasses.add( 0, lafClass );
|
lafClasses.add( 0, lafClass );
|
||||||
}
|
}
|
||||||
|
return lafClasses;
|
||||||
|
}
|
||||||
|
|
||||||
loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults );
|
static Properties newUIProperties( boolean dark ) {
|
||||||
|
// UI key prefixes
|
||||||
|
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( dark );
|
||||||
|
Set<String> platformPrefixes = FlatLaf.getUIKeyPlatformPrefixes();
|
||||||
|
Set<String> specialPrefixes = FlatLaf.getUIKeySpecialPrefixes();
|
||||||
|
|
||||||
|
return new Properties() {
|
||||||
|
@Override
|
||||||
|
public synchronized Object put( Object k, Object value ) {
|
||||||
|
// process key prefixes (while loading properties files)
|
||||||
|
String key = (String) k;
|
||||||
|
while( key.startsWith( "[" ) ) {
|
||||||
|
int closeIndex = key.indexOf( ']' );
|
||||||
|
if( closeIndex < 0 )
|
||||||
|
return null; // ignore property with invalid prefix
|
||||||
|
|
||||||
|
String prefix = key.substring( 0, closeIndex + 1 );
|
||||||
|
|
||||||
|
if( specialPrefixes.contains( prefix ) )
|
||||||
|
break; // keep special prefix
|
||||||
|
|
||||||
|
if( !lightOrDarkPrefix.equals( prefix ) && !platformPrefixes.contains( prefix ) )
|
||||||
|
return null; // ignore property
|
||||||
|
|
||||||
|
// prefix is known and enabled --> remove prefix
|
||||||
|
key = key.substring( closeIndex + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.put( key, value );
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
|
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
|
||||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
Consumer<Properties> intellijThemesHook, Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// temporary cache system colors while loading defaults,
|
// temporary cache system colors while loading defaults,
|
||||||
// which avoids that system color getter is invoked multiple times
|
// which avoids that system color getter is invoked multiple times
|
||||||
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
|
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
|
||||||
|
|
||||||
|
// all properties files will be loaded into this map
|
||||||
|
Properties properties = newUIProperties( dark );
|
||||||
|
|
||||||
// load core properties files
|
// load core properties files
|
||||||
Properties properties = new Properties();
|
|
||||||
for( Class<?> lafClass : lafClasses ) {
|
for( Class<?> lafClass : lafClasses ) {
|
||||||
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
|
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
|
||||||
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
|
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
|
||||||
@@ -142,6 +176,10 @@ class UIDefaultsLoader
|
|||||||
addonClassLoaders.add( addonClassLoader );
|
addonClassLoaders.add( addonClassLoader );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply IntelliJ themes properties
|
||||||
|
if( intellijThemesHook != null )
|
||||||
|
intellijThemesHook.accept( properties );
|
||||||
|
|
||||||
// load custom properties files (usually provided by applications)
|
// load custom properties files (usually provided by applications)
|
||||||
List<Object> customDefaultsSources = FlatLaf.getCustomDefaultsSources();
|
List<Object> customDefaultsSources = FlatLaf.getCustomDefaultsSources();
|
||||||
int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0;
|
int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0;
|
||||||
@@ -198,41 +236,6 @@ class UIDefaultsLoader
|
|||||||
if( additionalDefaults != null )
|
if( additionalDefaults != null )
|
||||||
properties.putAll( additionalDefaults );
|
properties.putAll( additionalDefaults );
|
||||||
|
|
||||||
// collect all platform specific keys (but do not modify properties)
|
|
||||||
ArrayList<String> platformSpecificKeys = new ArrayList<>();
|
|
||||||
for( Object okey : properties.keySet() ) {
|
|
||||||
String key = (String) okey;
|
|
||||||
if( key.startsWith( "[" ) &&
|
|
||||||
(key.startsWith( "[win]" ) ||
|
|
||||||
key.startsWith( "[mac]" ) ||
|
|
||||||
key.startsWith( "[linux]" ) ||
|
|
||||||
key.startsWith( "[light]" ) ||
|
|
||||||
key.startsWith( "[dark]" )) )
|
|
||||||
platformSpecificKeys.add( key );
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove platform specific properties and re-add only properties
|
|
||||||
// for current platform, but with platform prefix removed
|
|
||||||
if( !platformSpecificKeys.isEmpty() ) {
|
|
||||||
// handle light/dark specific properties
|
|
||||||
String lightOrDarkPrefix = dark ? "[dark]" : "[light]";
|
|
||||||
for( String key : platformSpecificKeys ) {
|
|
||||||
if( key.startsWith( lightOrDarkPrefix ) )
|
|
||||||
properties.put( key.substring( lightOrDarkPrefix.length() ), properties.remove( key ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle platform specific properties
|
|
||||||
String platformPrefix =
|
|
||||||
SystemInfo.isWindows ? "[win]" :
|
|
||||||
SystemInfo.isMacOS ? "[mac]" :
|
|
||||||
SystemInfo.isLinux ? "[linux]" : "[unknown]";
|
|
||||||
for( String key : platformSpecificKeys ) {
|
|
||||||
Object value = properties.remove( key );
|
|
||||||
if( key.startsWith( platformPrefix ) )
|
|
||||||
properties.put( key.substring( platformPrefix.length() ), value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get (and remove) wildcard replacements, which override all other defaults that end with same suffix
|
// get (and remove) wildcard replacements, which override all other defaults that end with same suffix
|
||||||
HashMap<String, String> wildcards = new HashMap<>();
|
HashMap<String, String> wildcards = new HashMap<>();
|
||||||
Iterator<Entry<Object, Object>> it = properties.entrySet().iterator();
|
Iterator<Entry<Object, Object>> it = properties.entrySet().iterator();
|
||||||
@@ -287,6 +290,15 @@ class UIDefaultsLoader
|
|||||||
// remember variables in defaults to allow using them in styles
|
// remember variables in defaults to allow using them in styles
|
||||||
defaults.put( KEY_VARIABLES, variables );
|
defaults.put( KEY_VARIABLES, variables );
|
||||||
|
|
||||||
|
// remember properties (for testing)
|
||||||
|
if( FlatSystemProperties.getBoolean( KEY_PROPERTIES, false ) ) {
|
||||||
|
Properties properties2 = new Properties();
|
||||||
|
properties2.putAll( properties );
|
||||||
|
for( Map.Entry<String, String> e : wildcards.entrySet() )
|
||||||
|
properties2.put( WILDCARD_PREFIX + e.getKey(), e.getValue() );
|
||||||
|
defaults.put( KEY_PROPERTIES, properties2 );
|
||||||
|
}
|
||||||
|
|
||||||
// clear/disable system color cache
|
// clear/disable system color cache
|
||||||
systemColorCache = null;
|
systemColorCache = null;
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
@@ -637,18 +649,26 @@ class UIDefaultsLoader
|
|||||||
if( value.indexOf( ',' ) >= 0 ) {
|
if( value.indexOf( ',' ) >= 0 ) {
|
||||||
// Syntax: top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
// Syntax: top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
||||||
List<String> parts = splitFunctionParams( value, ',' );
|
List<String> parts = splitFunctionParams( value, ',' );
|
||||||
Insets insets = parseInsets( value );
|
try {
|
||||||
ColorUIResource lineColor = (parts.size() >= 5)
|
Insets insets = parseInsets( value );
|
||||||
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver )
|
ColorUIResource lineColor = (parts.size() >= 5 && !parts.get( 4 ).isEmpty())
|
||||||
: null;
|
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver )
|
||||||
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty()) ? parseFloat( parts.get( 5 ) ) : 1f;
|
: null;
|
||||||
int arc = (parts.size() >= 7) ? parseInteger( parts.get( 6 ) ) : 0;
|
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty())
|
||||||
|
? parseFloat( parts.get( 5 ) )
|
||||||
|
: 1f;
|
||||||
|
int arc = (parts.size() >= 7) && !parts.get( 6 ).isEmpty()
|
||||||
|
? parseInteger( parts.get( 6 ) )
|
||||||
|
: -1;
|
||||||
|
|
||||||
return (LazyValue) t -> {
|
return (LazyValue) t -> {
|
||||||
return (lineColor != null)
|
return (lineColor != null || arc > 0)
|
||||||
? new FlatLineBorder( insets, lineColor, lineThickness, arc )
|
? new FlatLineBorder( insets, lineColor, lineThickness, arc )
|
||||||
: new FlatEmptyBorder( insets );
|
: new FlatEmptyBorder( insets );
|
||||||
};
|
};
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
throw new IllegalArgumentException( "invalid border '" + value + "' (" + ex.getMessage() + ")" );
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
return parseInstance( value, resolver, addonClassLoaders );
|
return parseInstance( value, resolver, addonClassLoaders );
|
||||||
}
|
}
|
||||||
@@ -719,7 +739,7 @@ class UIDefaultsLoader
|
|||||||
Integer.parseInt( numbers.get( 1 ) ),
|
Integer.parseInt( numbers.get( 1 ) ),
|
||||||
Integer.parseInt( numbers.get( 2 ) ),
|
Integer.parseInt( numbers.get( 2 ) ),
|
||||||
Integer.parseInt( numbers.get( 3 ) ) );
|
Integer.parseInt( numbers.get( 3 ) ) );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException | IndexOutOfBoundsException ex ) {
|
||||||
throw new IllegalArgumentException( "invalid insets '" + value + "'" );
|
throw new IllegalArgumentException( "invalid insets '" + value + "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -732,7 +752,7 @@ class UIDefaultsLoader
|
|||||||
return new DimensionUIResource(
|
return new DimensionUIResource(
|
||||||
Integer.parseInt( numbers.get( 0 ) ),
|
Integer.parseInt( numbers.get( 0 ) ),
|
||||||
Integer.parseInt( numbers.get( 1 ) ) );
|
Integer.parseInt( numbers.get( 1 ) ) );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException | IndexOutOfBoundsException ex ) {
|
||||||
throw new IllegalArgumentException( "invalid size '" + value + "'" );
|
throw new IllegalArgumentException( "invalid size '" + value + "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,6 +846,7 @@ class UIDefaultsLoader
|
|||||||
try {
|
try {
|
||||||
switch( function ) {
|
switch( function ) {
|
||||||
case "if": return parseColorIf( value, params, resolver );
|
case "if": return parseColorIf( value, params, resolver );
|
||||||
|
case "lazy": return parseColorLazy( value, params, resolver );
|
||||||
case "systemColor": return parseColorSystemColor( value, params, resolver );
|
case "systemColor": return parseColorSystemColor( value, params, resolver );
|
||||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
||||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
||||||
@@ -873,6 +894,32 @@ class UIDefaultsLoader
|
|||||||
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syntax: lazy(uiKey)
|
||||||
|
* <p>
|
||||||
|
* This "lazy" function is only used if the "lazy" is passed as parameter to another
|
||||||
|
* color function. Otherwise, the general "lazy" function is used.
|
||||||
|
* <p>
|
||||||
|
* Note: The color is resolved immediately, not lazy, because it is passed as parameter to another color function.
|
||||||
|
* So e.g. {@code darken(lazy(List.background), 10%)} is the same as {@code darken($List.background, 10%)}.
|
||||||
|
* <p>
|
||||||
|
* Only useful if a property is defined as lazy and that property is used
|
||||||
|
* in another property's color function. E.g.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* someProperty = lazy(List.background)
|
||||||
|
* anotherProperty = darken($someProperty, 10%)
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
|
private static Object parseColorLazy( String value, List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
if( params.size() != 1 )
|
||||||
|
throw newMissingParametersException( value );
|
||||||
|
|
||||||
|
return parseColorOrFunction( resolver.apply( PROPERTY_PREFIX + params.get( 0 ) ), resolver );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syntax: systemColor(name[,defaultValue])
|
* Syntax: systemColor(name[,defaultValue])
|
||||||
* - name: system color name
|
* - name: system color name
|
||||||
@@ -970,7 +1017,7 @@ class UIDefaultsLoader
|
|||||||
* fadein(color,amount[,options]) or fadeout(color,amount[,options])
|
* fadein(color,amount[,options]) or fadeout(color,amount[,options])
|
||||||
* - color: a color (e.g. #f00) or a color function
|
* - color: a color (e.g. #f00) or a color function
|
||||||
* - amount: percentage 0-100%
|
* - amount: percentage 0-100%
|
||||||
* - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
|
* - options: [relative] [autoInverse] [noAutoInverse] [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||||
List<String> params, Function<String, String> resolver )
|
List<String> params, Function<String, String> resolver )
|
||||||
@@ -980,15 +1027,15 @@ class UIDefaultsLoader
|
|||||||
int amount = parsePercentage( params.get( 1 ) );
|
int amount = parsePercentage( params.get( 1 ) );
|
||||||
boolean relative = false;
|
boolean relative = false;
|
||||||
boolean autoInverse = false;
|
boolean autoInverse = false;
|
||||||
boolean lazy = false;
|
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
|
boolean lazy = false;
|
||||||
|
|
||||||
if( params.size() > 2 ) {
|
if( params.size() > 2 ) {
|
||||||
String options = params.get( 2 );
|
String options = params.get( 2 );
|
||||||
relative = options.contains( "relative" );
|
relative = options.contains( "relative" );
|
||||||
autoInverse = options.contains( "autoInverse" );
|
autoInverse = options.contains( "autoInverse" );
|
||||||
lazy = options.contains( "lazy" );
|
|
||||||
derived = options.contains( "derived" );
|
derived = options.contains( "derived" );
|
||||||
|
lazy = options.contains( "lazy" );
|
||||||
|
|
||||||
// use autoInverse by default for derived colors, except if noAutoInverse is set
|
// use autoInverse by default for derived colors, except if noAutoInverse is set
|
||||||
if( derived && !options.contains( "noAutoInverse" ) )
|
if( derived && !options.contains( "noAutoInverse" ) )
|
||||||
@@ -999,14 +1046,8 @@ class UIDefaultsLoader
|
|||||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease(
|
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease(
|
||||||
hslIndex, increase, amount, relative, autoInverse );
|
hslIndex, increase, amount, relative, autoInverse );
|
||||||
|
|
||||||
if( lazy ) {
|
if( lazy )
|
||||||
return (LazyValue) t -> {
|
return newLazyColorFunction( colorStr, function );
|
||||||
Object color = lazyUIManagerGet( colorStr );
|
|
||||||
return (color instanceof Color)
|
|
||||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
|
||||||
: null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
@@ -1035,14 +1076,8 @@ class UIDefaultsLoader
|
|||||||
// create function
|
// create function
|
||||||
ColorFunction function = new ColorFunctions.Fade( amount );
|
ColorFunction function = new ColorFunctions.Fade( amount );
|
||||||
|
|
||||||
if( lazy ) {
|
if( lazy )
|
||||||
return (LazyValue) t -> {
|
return newLazyColorFunction( colorStr, function );
|
||||||
Object color = lazyUIManagerGet( colorStr );
|
|
||||||
return (color instanceof Color)
|
|
||||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
|
||||||
: null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
@@ -1052,7 +1087,7 @@ class UIDefaultsLoader
|
|||||||
* Syntax: spin(color,angle[,options])
|
* Syntax: spin(color,angle[,options])
|
||||||
* - color: a color (e.g. #f00) or a color function
|
* - color: a color (e.g. #f00) or a color function
|
||||||
* - angle: number of degrees to rotate
|
* - angle: number of degrees to rotate
|
||||||
* - options: [derived]
|
* - options: [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorSpin( List<String> params, Function<String, String> resolver )
|
private static Object parseColorSpin( List<String> params, Function<String, String> resolver )
|
||||||
throws IllegalArgumentException
|
throws IllegalArgumentException
|
||||||
@@ -1060,15 +1095,20 @@ class UIDefaultsLoader
|
|||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parseInteger( params.get( 1 ) );
|
int amount = parseInteger( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
|
boolean lazy = false;
|
||||||
|
|
||||||
if( params.size() > 2 ) {
|
if( params.size() > 2 ) {
|
||||||
String options = params.get( 2 );
|
String options = params.get( 2 );
|
||||||
derived = options.contains( "derived" );
|
derived = options.contains( "derived" );
|
||||||
|
lazy = options.contains( "lazy" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// create function
|
// create function
|
||||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
|
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
|
||||||
|
|
||||||
|
if( lazy )
|
||||||
|
return newLazyColorFunction( colorStr, function );
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
@@ -1080,7 +1120,7 @@ class UIDefaultsLoader
|
|||||||
* changeAlpha(color,value[,options])
|
* changeAlpha(color,value[,options])
|
||||||
* - color: a color (e.g. #f00) or a color function
|
* - color: a color (e.g. #f00) or a color function
|
||||||
* - value: for hue: number of degrees; otherwise: percentage 0-100%
|
* - value: for hue: number of degrees; otherwise: percentage 0-100%
|
||||||
* - options: [derived]
|
* - options: [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorChange( int hslIndex,
|
private static Object parseColorChange( int hslIndex,
|
||||||
List<String> params, Function<String, String> resolver )
|
List<String> params, Function<String, String> resolver )
|
||||||
@@ -1091,27 +1131,33 @@ class UIDefaultsLoader
|
|||||||
? parseInteger( params.get( 1 ) )
|
? parseInteger( params.get( 1 ) )
|
||||||
: parsePercentage( params.get( 1 ) );
|
: parsePercentage( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
|
boolean lazy = false;
|
||||||
|
|
||||||
if( params.size() > 2 ) {
|
if( params.size() > 2 ) {
|
||||||
String options = params.get( 2 );
|
String options = params.get( 2 );
|
||||||
derived = options.contains( "derived" );
|
derived = options.contains( "derived" );
|
||||||
|
lazy = options.contains( "lazy" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// create function
|
// create function
|
||||||
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
|
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
|
||||||
|
|
||||||
|
if( lazy )
|
||||||
|
return newLazyColorFunction( colorStr, function );
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syntax: mix(color1,color2[,weight]) or
|
* Syntax: mix(color1,color2[,weight][,options]) or
|
||||||
* tint(color[,weight]) or
|
* tint(color[,weight][,options]) or
|
||||||
* shade(color[,weight])
|
* shade(color[,weight][,options])
|
||||||
* - color1: a color (e.g. #f00) or a color function
|
* - color1: a color (e.g. #f00) or a color function
|
||||||
* - color2: a color (e.g. #f00) or a color function
|
* - color2: a color (e.g. #f00) or a color function
|
||||||
* - weight: the weight (in range 0-100%) to mix the two colors
|
* - weight: the weight (in range 0-100%) to mix the two colors
|
||||||
* larger weight uses more of first color, smaller weight more of second color
|
* larger weight uses more of first color, smaller weight more of second color
|
||||||
|
* - options: [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver )
|
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver )
|
||||||
throws IllegalArgumentException
|
throws IllegalArgumentException
|
||||||
@@ -1120,18 +1166,36 @@ class UIDefaultsLoader
|
|||||||
if( color1Str == null )
|
if( color1Str == null )
|
||||||
color1Str = params.get( i++ );
|
color1Str = params.get( i++ );
|
||||||
String color2Str = params.get( i++ );
|
String color2Str = params.get( i++ );
|
||||||
int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
|
int weight = 50;
|
||||||
|
boolean derived = false;
|
||||||
|
boolean lazy = false;
|
||||||
|
|
||||||
|
if( params.size() > i ) {
|
||||||
|
String weightStr = params.get( i );
|
||||||
|
if( !weightStr.isEmpty() && Character.isDigit( weightStr.charAt( 0 ) ) ) {
|
||||||
|
weight = parsePercentage( weightStr );
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( params.size() > i ) {
|
||||||
|
String options = params.get( i );
|
||||||
|
derived = options.contains( "derived" );
|
||||||
|
lazy = options.contains( "lazy" );
|
||||||
|
}
|
||||||
|
|
||||||
// parse second color
|
// parse second color
|
||||||
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver );
|
ColorUIResource color1 = (ColorUIResource) parseColorOrFunction( resolver.apply( color1Str ), resolver );
|
||||||
if( color2 == null )
|
if( color1 == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// create function
|
// create function
|
||||||
ColorFunction function = new ColorFunctions.Mix( color2, weight );
|
ColorFunction function = new ColorFunctions.Mix2( color1, weight );
|
||||||
|
|
||||||
|
if( lazy )
|
||||||
|
return newLazyColorFunction( color2Str, function );
|
||||||
|
|
||||||
// parse first color, apply function and create mixed color
|
// parse first color, apply function and create mixed color
|
||||||
return parseFunctionBaseColor( color1Str, function, false, resolver );
|
return parseFunctionBaseColor( color2Str, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1225,6 +1289,15 @@ class UIDefaultsLoader
|
|||||||
return new ColorUIResource( newColor );
|
return new ColorUIResource( newColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static LazyValue newLazyColorFunction( String uiKey, ColorFunction function ) {
|
||||||
|
return (LazyValue) t -> {
|
||||||
|
Object color = lazyUIManagerGet( uiKey );
|
||||||
|
return (color instanceof Color)
|
||||||
|
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
||||||
*/
|
*/
|
||||||
@@ -1310,17 +1383,17 @@ class UIDefaultsLoader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch( IOException ex ) {
|
} catch( RuntimeException | IOException ex ) {
|
||||||
throw new IllegalArgumentException( ex );
|
throw new IllegalArgumentException( "invalid font '" + value + "' (" + ex.getMessage() + ")" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( style != -1 && styleChange != 0 )
|
if( style != -1 && styleChange != 0 )
|
||||||
throw new IllegalArgumentException( "can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic') in '" + value + "'" );
|
throw new IllegalArgumentException( "invalid font '" + value + "': can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic')" );
|
||||||
if( styleChange != 0 ) {
|
if( styleChange != 0 ) {
|
||||||
if( (styleChange & Font.BOLD) != 0 && (styleChange & (Font.BOLD << 16)) != 0 )
|
if( (styleChange & Font.BOLD) != 0 && (styleChange & (Font.BOLD << 16)) != 0 )
|
||||||
throw new IllegalArgumentException( "can not use '+bold' and '-bold' in '" + value + "'" );
|
throw new IllegalArgumentException( "invalid font '" + value + "': can not use '+bold' and '-bold'" );
|
||||||
if( (styleChange & Font.ITALIC) != 0 && (styleChange & (Font.ITALIC << 16)) != 0 )
|
if( (styleChange & Font.ITALIC) != 0 && (styleChange & (Font.ITALIC << 16)) != 0 )
|
||||||
throw new IllegalArgumentException( "can not use '+italic' and '-italic' in '" + value + "'" );
|
throw new IllegalArgumentException( "invalid font '" + value + "': can not use '+italic' and '-italic'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
||||||
@@ -1460,7 +1533,7 @@ class UIDefaultsLoader
|
|||||||
return (LazyValue) t -> {
|
return (LazyValue) t -> {
|
||||||
return new GrayFilter( brightness, contrast, alpha );
|
return new GrayFilter( brightness, contrast, alpha );
|
||||||
};
|
};
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException | IndexOutOfBoundsException ex ) {
|
||||||
throw new IllegalArgumentException( "invalid gray filter '" + value + "'" );
|
throw new IllegalArgumentException( "invalid gray filter '" + value + "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,76 +18,141 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Window;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTitlePane;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for window icons.
|
* Base class for window icons.
|
||||||
*
|
*
|
||||||
* @uiDefault TitlePane.buttonSize Dimension
|
* @uiDefault TitlePane.buttonSize Dimension
|
||||||
|
* @uiDefault TitlePane.buttonInsets Insets optional
|
||||||
|
* @uiDefault TitlePane.buttonArc int optional
|
||||||
* @uiDefault TitlePane.buttonSymbolHeight int
|
* @uiDefault TitlePane.buttonSymbolHeight int
|
||||||
* @uiDefault TitlePane.buttonHoverBackground Color
|
* @uiDefault TitlePane.buttonBackground Color optional
|
||||||
* @uiDefault TitlePane.buttonPressedBackground Color
|
* @uiDefault TitlePane.buttonForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonInactiveBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonInactiveForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonHoverBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonHoverForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonPressedBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonPressedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public abstract class FlatWindowAbstractIcon
|
public abstract class FlatWindowAbstractIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
private final int symbolHeight;
|
/** @since 3.6 */ protected final Insets insets;
|
||||||
private final Color hoverBackground;
|
/** @since 3.6 */ protected final int arc;
|
||||||
private final Color pressedBackground;
|
/** @since 3.6 */ protected final int symbolHeight;
|
||||||
|
|
||||||
|
/** @since 3.6 */ protected final Color background;
|
||||||
|
/** @since 3.6 */ protected final Color foreground;
|
||||||
|
/** @since 3.6 */ protected final Color inactiveBackground;
|
||||||
|
/** @since 3.6 */ protected final Color inactiveForeground;
|
||||||
|
protected final Color hoverBackground;
|
||||||
|
/** @since 3.6 */ protected final Color hoverForeground;
|
||||||
|
protected final Color pressedBackground;
|
||||||
|
/** @since 3.6 */ protected final Color pressedForeground;
|
||||||
|
|
||||||
/** @since 3.2 */
|
/** @since 3.2 */
|
||||||
protected FlatWindowAbstractIcon( String windowStyle ) {
|
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||||
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
this( windowStyle, null, null, null, null, null, null, null, null );
|
||||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
|
||||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
|
||||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.2 */
|
/** @since 3.6 */
|
||||||
protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
|
protected FlatWindowAbstractIcon( String windowStyle,
|
||||||
|
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||||
|
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||||
|
{
|
||||||
|
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIInsets( "TitlePane.buttonInsets", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonArc", windowStyle, 0 ),
|
||||||
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||||
|
(background != null) ? background : FlatUIUtils.getSubUIColor( "TitlePane.buttonBackground", windowStyle ),
|
||||||
|
(foreground != null) ? foreground : FlatUIUtils.getSubUIColor( "TitlePane.buttonForeground", windowStyle ),
|
||||||
|
(inactiveBackground != null) ? inactiveBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveBackground", windowStyle ),
|
||||||
|
(inactiveForeground != null) ? inactiveForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveForeground", windowStyle ),
|
||||||
|
(hoverBackground != null) ? hoverBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||||
|
(hoverForeground != null) ? hoverForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverForeground", windowStyle ),
|
||||||
|
(pressedBackground != null) ? pressedBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ),
|
||||||
|
(pressedForeground != null) ? pressedForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedForeground", windowStyle ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.6 */
|
||||||
|
protected FlatWindowAbstractIcon( Dimension size, Insets insets, int arc, int symbolHeight,
|
||||||
|
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||||
|
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||||
|
{
|
||||||
super( size.width, size.height, null );
|
super( size.width, size.height, null );
|
||||||
|
this.insets = (insets != null) ? insets : new Insets( 0, 0, 0, 0 );
|
||||||
|
this.arc = arc;
|
||||||
this.symbolHeight = symbolHeight;
|
this.symbolHeight = symbolHeight;
|
||||||
|
|
||||||
|
this.background = background;
|
||||||
|
this.foreground = foreground;
|
||||||
|
this.inactiveBackground = inactiveBackground;
|
||||||
|
this.inactiveForeground = inactiveForeground;
|
||||||
this.hoverBackground = hoverBackground;
|
this.hoverBackground = hoverBackground;
|
||||||
|
this.hoverForeground = hoverForeground;
|
||||||
this.pressedBackground = pressedBackground;
|
this.pressedBackground = pressedBackground;
|
||||||
|
this.pressedForeground = pressedForeground;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 */
|
||||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
@Override
|
||||||
|
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||||
|
Color bg = null;
|
||||||
|
if( background != null || inactiveBackground != null ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
|
bg = (window == null || window.isActive()) ? background : inactiveBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color background = FlatButtonUI.buttonStateColor( c, bg, 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%)
|
Insets insets = UIScale.scale( this.insets );
|
||||||
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
float arc = UIScale.scale( (float) this.arc );
|
||||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
|
||||||
|
|
||||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
// derive color from title pane background
|
||||||
g.fillRect( 0, 0, width, height );
|
if( background instanceof DerivedColor ) {
|
||||||
|
Container titlePane = SwingUtilities.getAncestorOfClass( FlatTitlePane.class, c );
|
||||||
|
Component baseComp = (titlePane != null) ? titlePane : c;
|
||||||
|
background = FlatUIUtils.deriveColor( background, baseComp.getBackground() );
|
||||||
|
}
|
||||||
|
|
||||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
g.setColor( background );
|
||||||
|
FlatUIUtils.paintComponentBackground( g, insets.left, insets.top,
|
||||||
|
c.getWidth() - insets.left - insets.right,
|
||||||
|
c.getHeight() - insets.top - insets.bottom,
|
||||||
|
0, arc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( Component c ) {
|
protected Color getForeground( Component c ) {
|
||||||
return c.getForeground();
|
Color fg = null;
|
||||||
}
|
if( foreground != null || inactiveForeground != null ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
/** @since 3.2 */
|
fg = (window == null || window.isActive()) ? foreground : inactiveForeground;
|
||||||
protected int getSymbolHeight() {
|
}
|
||||||
return symbolHeight;
|
return FlatButtonUI.buttonStateColor( c, (fg != null) ? fg : c.getForeground(),
|
||||||
|
null, null, hoverForeground, pressedForeground );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,53 +17,54 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "close" icon for windows (frames and dialogs).
|
* "close" icon for windows (frames and dialogs).
|
||||||
*
|
*
|
||||||
* @uiDefault TitlePane.closeHoverBackground Color
|
* @uiDefault TitlePane.closeBackground Color optional
|
||||||
* @uiDefault TitlePane.closePressedBackground Color
|
* @uiDefault TitlePane.closeForeground Color optional
|
||||||
* @uiDefault TitlePane.closeHoverForeground Color
|
* @uiDefault TitlePane.closeInactiveBackground Color optional
|
||||||
* @uiDefault TitlePane.closePressedForeground Color
|
* @uiDefault TitlePane.closeInactiveForeground Color optional
|
||||||
|
* @uiDefault TitlePane.closeHoverBackground Color optional
|
||||||
|
* @uiDefault TitlePane.closeHoverForeground Color optional
|
||||||
|
* @uiDefault TitlePane.closePressedBackground Color optional
|
||||||
|
* @uiDefault TitlePane.closePressedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatWindowCloseIcon
|
public class FlatWindowCloseIcon
|
||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
private final Color hoverForeground;
|
|
||||||
private final Color pressedForeground;
|
|
||||||
|
|
||||||
public FlatWindowCloseIcon() {
|
public FlatWindowCloseIcon() {
|
||||||
this( null );
|
this( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.2 */
|
/** @since 3.2 */
|
||||||
public FlatWindowCloseIcon( String windowStyle ) {
|
public FlatWindowCloseIcon( String windowStyle ) {
|
||||||
super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
super( windowStyle,
|
||||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
FlatUIUtils.getSubUIColor( "TitlePane.closeBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeForeground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveForeground", windowStyle ),
|
||||||
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
|
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ),
|
||||||
hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
|
FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle ) );
|
||||||
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 iwh = (int) (getSymbolHeight() * scaleFactor);
|
int iwh = (int) (symbolHeight * 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);
|
||||||
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;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) 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 );
|
||||||
@@ -73,9 +74,4 @@ public class FlatWindowCloseIcon
|
|||||||
g.setStroke( new BasicStroke( thickness ) );
|
g.setStroke( new BasicStroke( thickness ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Color getForeground( Component c ) {
|
|
||||||
return FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ 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) (symbolHeight * 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);
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,11 @@ public class FlatWindowMaximizeIcon
|
|||||||
|
|
||||||
@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 iwh = (int) (getSymbolHeight() * scaleFactor);
|
int iwh = (int) (symbolHeight * 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;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) 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
|
||||||
|
|||||||
@@ -42,14 +42,15 @@ public class FlatWindowRestoreIcon
|
|||||||
|
|
||||||
@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 iwh = (int) (getSymbolHeight() * scaleFactor);
|
int iwh = (int) (symbolHeight * 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;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) 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));
|
||||||
|
|
||||||
int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
|
int rwh = (int) ((symbolHeight - 2) * scaleFactor);
|
||||||
int ro2 = iwh - rwh;
|
int ro2 = iwh - rwh;
|
||||||
|
|
||||||
// upper-right rectangle
|
// upper-right rectangle
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ import com.formdev.flatlaf.util.DerivedColor;
|
|||||||
* @uiDefault Component.error.focusedBorderColor Color
|
* @uiDefault Component.error.focusedBorderColor Color
|
||||||
* @uiDefault Component.warning.borderColor Color
|
* @uiDefault Component.warning.borderColor Color
|
||||||
* @uiDefault Component.warning.focusedBorderColor Color
|
* @uiDefault Component.warning.focusedBorderColor Color
|
||||||
|
* @uiDefault Component.success.borderColor Color
|
||||||
|
* @uiDefault Component.success.focusedBorderColor Color
|
||||||
* @uiDefault Component.custom.borderColor Color
|
* @uiDefault Component.custom.borderColor Color
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -81,6 +83,8 @@ public class FlatBorder
|
|||||||
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||||
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||||
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||||
|
/** @since 3.6 */ @Styleable(dot=true) protected Color successBorderColor = UIManager.getColor( "Component.success.borderColor" );
|
||||||
|
/** @since 3.6 */ @Styleable(dot=true) protected Color successFocusedBorderColor = UIManager.getColor( "Component.success.focusedBorderColor" );
|
||||||
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||||
|
|
||||||
// only used via styling (not in UI defaults, but has likewise client properties)
|
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||||
@@ -135,7 +139,7 @@ public class FlatBorder
|
|||||||
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
||||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
||||||
focusColor, borderColor, null );
|
focusColor, borderColor, null, c instanceof JScrollPane );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
@@ -168,6 +172,9 @@ public class FlatBorder
|
|||||||
|
|
||||||
case FlatClientProperties.OUTLINE_WARNING:
|
case FlatClientProperties.OUTLINE_WARNING:
|
||||||
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
||||||
|
|
||||||
|
case FlatClientProperties.OUTLINE_SUCCESS:
|
||||||
|
return isFocused( c ) ? successFocusedBorderColor : successBorderColor;
|
||||||
}
|
}
|
||||||
} else if( outline instanceof Color ) {
|
} else if( outline instanceof Color ) {
|
||||||
Color color = (Color) outline;
|
Color color = (Color) outline;
|
||||||
@@ -277,7 +284,7 @@ public class FlatBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the (unscaled) arc diameter of the border.
|
* Returns the (unscaled) arc diameter of the border corners.
|
||||||
*/
|
*/
|
||||||
protected int getArc( Component c ) {
|
protected int getArc( Component c ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.disabledBorderColor Color
|
* @uiDefault Button.disabledBorderColor Color
|
||||||
* @uiDefault Button.focusedBorderColor Color
|
* @uiDefault Button.focusedBorderColor Color
|
||||||
* @uiDefault Button.hoverBorderColor Color optional
|
* @uiDefault Button.hoverBorderColor Color optional
|
||||||
|
* @uiDefault Button.pressedBorderColor Color optional
|
||||||
|
*
|
||||||
|
* @uiDefault Button.selectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.disabledSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.focusedSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.hoverSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.pressedSelectedBorderColor Color optional
|
||||||
*
|
*
|
||||||
* @uiDefault Button.default.borderWidth int or float
|
* @uiDefault Button.default.borderWidth int or float
|
||||||
* @uiDefault Button.default.borderColor Color
|
* @uiDefault Button.default.borderColor Color
|
||||||
@@ -49,6 +56,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.focusedBorderColor Color
|
* @uiDefault Button.default.focusedBorderColor Color
|
||||||
* @uiDefault Button.default.focusColor Color
|
* @uiDefault Button.default.focusColor Color
|
||||||
|
* @uiDefault Button.default.pressedBorderColor Color optional
|
||||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
* @uiDefault Button.default.hoverBorderColor Color optional
|
||||||
*
|
*
|
||||||
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1.5
|
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1.5
|
||||||
@@ -65,6 +73,13 @@ public class FlatButtonBorder
|
|||||||
|
|
||||||
protected Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
protected Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
||||||
@Styleable protected Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
@Styleable protected Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable protected Color pressedBorderColor = UIManager.getColor( "Button.pressedBorderColor" );
|
||||||
|
|
||||||
|
/** @since 3.5 */ @Styleable protected Color selectedBorderColor = UIManager.getColor( "Button.selectedBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable protected Color disabledSelectedBorderColor = UIManager.getColor( "Button.disabledSelectedBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable protected Color focusedSelectedBorderColor = UIManager.getColor( "Button.focusedSelectedBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable protected Color hoverSelectedBorderColor = UIManager.getColor( "Button.hoverSelectedBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable protected Color pressedSelectedBorderColor = UIManager.getColor( "Button.pressedSelectedBorderColor" );
|
||||||
|
|
||||||
@Styleable(dot=true) protected float defaultBorderWidth = FlatUIUtils.getUIFloat( "Button.default.borderWidth", 1 );
|
@Styleable(dot=true) protected float defaultBorderWidth = FlatUIUtils.getUIFloat( "Button.default.borderWidth", 1 );
|
||||||
@Styleable(dot=true) protected Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
@Styleable(dot=true) protected Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
||||||
@@ -72,6 +87,7 @@ public class FlatButtonBorder
|
|||||||
@Styleable(dot=true) protected Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
@Styleable(dot=true) protected Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||||
@Styleable(dot=true) protected Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
@Styleable(dot=true) protected Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||||
@Styleable(dot=true) protected Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
@Styleable(dot=true) protected Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable(dot=true) protected Color defaultPressedBorderColor = UIManager.getColor( "Button.default.pressedBorderColor" );
|
||||||
|
|
||||||
/** @since 1.4 */ @Styleable(dot=true) protected float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
/** @since 1.4 */ @Styleable(dot=true) protected float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
||||||
/** @since 1.4 */ @Styleable(dot=true) protected Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
/** @since 1.4 */ @Styleable(dot=true) protected Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
||||||
@@ -139,12 +155,13 @@ public class FlatButtonBorder
|
|||||||
@Override
|
@Override
|
||||||
protected Paint getBorderColor( Component c ) {
|
protected Paint getBorderColor( Component c ) {
|
||||||
boolean def = FlatButtonUI.isDefaultButton( c );
|
boolean def = FlatButtonUI.isDefaultButton( c );
|
||||||
|
boolean selected = (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
|
||||||
Paint color = FlatButtonUI.buttonStateColor( c,
|
Paint color = FlatButtonUI.buttonStateColor( c,
|
||||||
def ? defaultBorderColor : borderColor,
|
def ? defaultBorderColor : ((selected && selectedBorderColor != null) ? selectedBorderColor : borderColor),
|
||||||
disabledBorderColor,
|
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor,
|
||||||
def ? defaultFocusedBorderColor : focusedBorderColor,
|
def ? defaultFocusedBorderColor : ((selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor),
|
||||||
def ? defaultHoverBorderColor : hoverBorderColor,
|
def ? defaultHoverBorderColor : ((selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor),
|
||||||
null );
|
def ? defaultPressedBorderColor : ((selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor) );
|
||||||
|
|
||||||
// change to gradient paint if start/end colors are specified
|
// change to gradient paint if start/end colors are specified
|
||||||
Color startBg = def ? defaultBorderColor : borderColor;
|
Color startBg = def ? defaultBorderColor : borderColor;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -61,6 +62,7 @@ import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -278,8 +280,6 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
LookAndFeel.installProperty( b, "opaque", false );
|
LookAndFeel.installProperty( b, "opaque", false );
|
||||||
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
||||||
|
|
||||||
MigLayoutVisualPadding.install( b );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -289,10 +289,23 @@ public class FlatButtonUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
borderShared = null;
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( b );
|
|
||||||
defaults_initialized = false;
|
defaults_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installListeners( AbstractButton b ) {
|
||||||
|
super.installListeners( b );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.install( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallListeners( AbstractButton b ) {
|
||||||
|
super.uninstallListeners( b );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.uninstall( b );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
||||||
return new FlatButtonListener( b );
|
return new FlatButtonListener( b );
|
||||||
@@ -300,6 +313,10 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
|
case BasicHTML.propertyKey:
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( b );
|
||||||
|
break;
|
||||||
|
|
||||||
case SQUARE_SIZE:
|
case SQUARE_SIZE:
|
||||||
case MINIMUM_WIDTH:
|
case MINIMUM_WIDTH:
|
||||||
case MINIMUM_HEIGHT:
|
case MINIMUM_HEIGHT:
|
||||||
@@ -308,11 +325,11 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
case BUTTON_TYPE:
|
case BUTTON_TYPE:
|
||||||
b.revalidate();
|
b.revalidate();
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTLINE:
|
case OUTLINE:
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STYLE:
|
case STYLE:
|
||||||
@@ -324,7 +341,7 @@ public class FlatButtonUI
|
|||||||
} else
|
} else
|
||||||
installStyle( b );
|
installStyle( b );
|
||||||
b.revalidate();
|
b.revalidate();
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,6 +381,12 @@ public class FlatButtonUI
|
|||||||
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update internal values; otherwise isCustomBackground() and isCustomForeground() would return wrong results
|
||||||
|
switch( key ) {
|
||||||
|
case "background": background = (Color) value; break;
|
||||||
|
case "foreground": foreground = (Color) value; break;
|
||||||
|
}
|
||||||
|
|
||||||
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
||||||
value = UIScale.scale( (Integer) value );
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
@@ -583,9 +606,16 @@ public class FlatButtonUI
|
|||||||
// paint text
|
// paint text
|
||||||
if( clippedText != null && !clippedText.isEmpty() ) {
|
if( clippedText != null && !clippedText.isEmpty() ) {
|
||||||
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
||||||
if( view != null )
|
if( view != null ) {
|
||||||
|
// update foreground color in HTML view, which is necessary
|
||||||
|
// for selected and pressed states
|
||||||
|
// (only for enabled buttons, because UIManager.getColor("textInactiveText")
|
||||||
|
// is used for disabled components; see: javax.swing.text.GlyphView.paint())
|
||||||
|
if( b.isEnabled() )
|
||||||
|
FlatHTML.updateRendererCSSForeground( view, getForeground( b ) );
|
||||||
|
|
||||||
view.paint( g, textR ); // HTML text
|
view.paint( g, textR ); // HTML text
|
||||||
else
|
} else
|
||||||
paintText( g, b, textR, clippedText );
|
paintText( g, b, textR, clippedText );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,8 +661,6 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
||||||
if(foreground == null)
|
|
||||||
foreground=Color.red;
|
|
||||||
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
||||||
|
|
||||||
@@ -642,7 +670,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() ) {
|
||||||
@@ -670,7 +699,6 @@ public class FlatButtonUI
|
|||||||
toolbarPressedBackground );
|
toolbarPressedBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
getBackgroundBase( c, def ),
|
getBackgroundBase( c, def ),
|
||||||
disabledBackground,
|
disabledBackground,
|
||||||
@@ -722,7 +750,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() ) {
|
||||||
@@ -748,7 +777,6 @@ public class FlatButtonUI
|
|||||||
toolbarPressedForeground );
|
toolbarPressedForeground );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
getForegroundBase( c, def ),
|
getForegroundBase( c, def ),
|
||||||
disabledText,
|
disabledText,
|
||||||
@@ -906,7 +934,7 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged( ChangeEvent e ) {
|
public void stateChanged( ChangeEvent e ) {
|
||||||
super.stateChanged( e );
|
HiDPIUtils.repaint( b );
|
||||||
|
|
||||||
// if button is in toolbar, repaint button groups
|
// if button is in toolbar, repaint button groups
|
||||||
AbstractButton b = (AbstractButton) e.getSource();
|
AbstractButton b = (AbstractButton) e.getSource();
|
||||||
@@ -918,5 +946,17 @@ public class FlatButtonUI
|
|||||||
((FlatToolBarUI)ui).repaintButtonGroup( b );
|
((FlatToolBarUI)ui).repaintButtonGroup( b );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusGained( FocusEvent e ) {
|
||||||
|
super.focusGained( e );
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost( FocusEvent e ) {
|
||||||
|
super.focusLost( e );
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
@@ -24,7 +25,9 @@ import java.awt.event.FocusEvent;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JFormattedTextField;
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
@@ -33,6 +36,7 @@ import javax.swing.text.DefaultCaret;
|
|||||||
import javax.swing.text.DefaultEditorKit;
|
import javax.swing.text.DefaultEditorKit;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import javax.swing.text.Position;
|
||||||
import javax.swing.text.Utilities;
|
import javax.swing.text.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,12 +52,15 @@ public class FlatCaret
|
|||||||
{
|
{
|
||||||
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
|
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
|
||||||
|
|
||||||
|
// selectAllOnFocusPolicy
|
||||||
|
private static final int NEVER = 0, ONCE = 1, ALWAYS = 2;
|
||||||
|
|
||||||
private final String selectAllOnFocusPolicy;
|
private final String selectAllOnFocusPolicy;
|
||||||
private final boolean selectAllOnMouseClick;
|
private final boolean selectAllOnMouseClick;
|
||||||
|
|
||||||
private boolean inInstall;
|
private boolean inInstall;
|
||||||
private boolean wasFocused;
|
private boolean wasFocused;
|
||||||
private boolean wasTemporaryLost;
|
private boolean wasFocusTemporaryLost;
|
||||||
private boolean isMousePressed;
|
private boolean isMousePressed;
|
||||||
private boolean isWordSelection;
|
private boolean isWordSelection;
|
||||||
private boolean isLineSelection;
|
private boolean isLineSelection;
|
||||||
@@ -94,6 +101,9 @@ public class FlatCaret
|
|||||||
// restore selection
|
// restore selection
|
||||||
select( (int) ci[1], (int) ci[0] );
|
select( (int) ci[1], (int) ci[0] );
|
||||||
|
|
||||||
|
if( ci[4] != 0 )
|
||||||
|
wasFocused = true;
|
||||||
|
|
||||||
// if text component is focused, then caret and selection are visible,
|
// if text component is focused, then caret and selection are visible,
|
||||||
// but when switching theme, the component does not yet have
|
// but when switching theme, the component does not yet have
|
||||||
// a highlighter and the selection is not painted
|
// a highlighter and the selection is not painted
|
||||||
@@ -121,6 +131,7 @@ public class FlatCaret
|
|||||||
getMark(),
|
getMark(),
|
||||||
getBlinkRate(),
|
getBlinkRate(),
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
|
wasFocused ? 1 : 0,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
super.deinstall( c );
|
super.deinstall( c );
|
||||||
@@ -140,11 +151,36 @@ public class FlatCaret
|
|||||||
super.adjustVisibility( nloc );
|
super.adjustVisibility( nloc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDot( int dot ) {
|
||||||
|
super.setDot( dot );
|
||||||
|
|
||||||
|
// mark as focused if invoked from JTextComponent.setCaretPosition()
|
||||||
|
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
|
||||||
|
if( !wasFocused &&
|
||||||
|
getSelectAllOnFocusPolicy() == ONCE &&
|
||||||
|
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "setCaretPosition", 6 ) )
|
||||||
|
wasFocused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveDot( int dot ) {
|
||||||
|
super.moveDot( dot );
|
||||||
|
|
||||||
|
// mark as focused if invoked from JTextComponent.moveCaretPosition()
|
||||||
|
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
|
||||||
|
if( !wasFocused &&
|
||||||
|
getSelectAllOnFocusPolicy() == ONCE &&
|
||||||
|
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "moveCaretPosition", 6 ) )
|
||||||
|
wasFocused = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
if( !inInstall && !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
if( !inInstall && !wasFocusTemporaryLost && (!isMousePressed || isSelectAllOnMouseClick()) )
|
||||||
selectAllOnFocusGained();
|
selectAllOnFocusGained();
|
||||||
wasTemporaryLost = false;
|
|
||||||
|
wasFocusTemporaryLost = false;
|
||||||
wasFocused = true;
|
wasFocused = true;
|
||||||
|
|
||||||
super.focusGained( e );
|
super.focusGained( e );
|
||||||
@@ -152,7 +188,7 @@ public class FlatCaret
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
wasTemporaryLost = e.isTemporary();
|
wasFocusTemporaryLost = e.isTemporary();
|
||||||
super.focusLost( e );
|
super.focusLost( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,24 +268,13 @@ public class FlatCaret
|
|||||||
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
|
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
int selectAllOnFocusPolicy = getSelectAllOnFocusPolicy();
|
||||||
if( selectAllOnFocusPolicy == null )
|
if( selectAllOnFocusPolicy == NEVER )
|
||||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
|
||||||
|
|
||||||
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
if( selectAllOnFocusPolicy == ONCE && !isMousePressed ) {
|
||||||
// policy is "once" (or null or unknown)
|
|
||||||
|
|
||||||
// was already focused?
|
// was already focused?
|
||||||
if( wasFocused )
|
if( wasFocused && !(c instanceof JFormattedTextField) )
|
||||||
return;
|
|
||||||
|
|
||||||
// check whether selection was modified before gaining focus
|
|
||||||
int dot = getDot();
|
|
||||||
int mark = getMark();
|
|
||||||
if( dot != mark || dot != doc.getLength() )
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,16 +290,51 @@ public class FlatCaret
|
|||||||
|
|
||||||
select( 0, c2.getDocument().getLength() );
|
select( 0, c2.getDocument().getLength() );
|
||||||
} );
|
} );
|
||||||
} else {
|
} else
|
||||||
select( 0, doc.getLength() );
|
select( 0, doc.getLength() );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void select( int mark, int dot ) {
|
private void select( int mark, int dot ) {
|
||||||
if( mark != getMark() )
|
if( mark != getMark() )
|
||||||
setDot( mark );
|
setDot( mark, Position.Bias.Forward );
|
||||||
if( dot != getDot() )
|
if( dot != getDot() )
|
||||||
moveDot( dot );
|
moveDot( dot, Position.Bias.Forward );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelectAllOnFocusPolicy() {
|
||||||
|
Object value = getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
||||||
|
// Note: using String.valueOf() because selectAllOnFocusPolicy may be null
|
||||||
|
switch( String.valueOf( value instanceof String ? value : selectAllOnFocusPolicy ) ) {
|
||||||
|
default:
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_NEVER: return NEVER;
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_ONCE: return ONCE;
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_ALWAYS: return ALWAYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSelectAllOnMouseClick() {
|
||||||
|
Object value = getClientProperty( SELECT_ALL_ON_MOUSE_CLICK );
|
||||||
|
return (value instanceof Boolean) ? (boolean) value : selectAllOnMouseClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getClientProperty( String key ) {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
if( c == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Object value = c.getClientProperty( key );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
|
||||||
|
Container parent = c.getParent();
|
||||||
|
if( parent instanceof JComboBox )
|
||||||
|
return ((JComboBox<?>)parent).getClientProperty( key );
|
||||||
|
if( parent instanceof JSpinner.DefaultEditor ) {
|
||||||
|
parent = parent.getParent();
|
||||||
|
if( parent instanceof JSpinner )
|
||||||
|
return ((JSpinner)parent).getClientProperty( key );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 1.4 */
|
/** @since 1.4 */
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.lang.invoke.MethodHandles;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||||
@@ -102,13 +103,23 @@ public class FlatCheckBoxMenuItemUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents( JMenuItem menuItem ) {
|
||||||
|
super.installComponents( menuItem );
|
||||||
|
|
||||||
|
// update HTML renderer if necessary
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||||
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
return FlatHTML.createPropertyChangeListener(
|
||||||
|
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||||
|
super.createPropertyChangeListener( c ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
@@ -220,10 +221,12 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
private void repaintArrowButton() {
|
private void repaintArrowButton() {
|
||||||
if( arrowButton != null && !comboBox.isEditable() )
|
if( arrowButton != null && !comboBox.isEditable() )
|
||||||
arrowButton.repaint();
|
HiDPIUtils.repaint( arrowButton );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
comboBox.addMouseListener( hoverListener );
|
comboBox.addMouseListener( hoverListener );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.install( comboBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -232,6 +235,8 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
comboBox.removeMouseListener( hoverListener );
|
comboBox.removeMouseListener( hoverListener );
|
||||||
hoverListener = null;
|
hoverListener = null;
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.uninstall( comboBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -273,8 +278,6 @@ public class FlatComboBoxUI
|
|||||||
comboBox.setMaximumRowCount( maximumRowCount );
|
comboBox.setMaximumRowCount( maximumRowCount );
|
||||||
|
|
||||||
paddingBorder = new CellPaddingBorder( padding );
|
paddingBorder = new CellPaddingBorder( padding );
|
||||||
|
|
||||||
MigLayoutVisualPadding.install( comboBox );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -303,8 +306,6 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
borderShared = null;
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( comboBox );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -351,15 +352,15 @@ public class FlatComboBoxUI
|
|||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
super.focusGained( e );
|
super.focusGained( e );
|
||||||
if( comboBox != null && comboBox.isEditable() )
|
if( comboBox != null )
|
||||||
comboBox.repaint();
|
HiDPIUtils.repaint( comboBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
super.focusLost( e );
|
super.focusLost( e );
|
||||||
if( comboBox != null && comboBox.isEditable() )
|
if( comboBox != null )
|
||||||
comboBox.repaint();
|
HiDPIUtils.repaint( comboBox );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -386,12 +387,12 @@ public class FlatComboBoxUI
|
|||||||
switch( propertyName ) {
|
switch( propertyName ) {
|
||||||
case PLACEHOLDER_TEXT:
|
case PLACEHOLDER_TEXT:
|
||||||
if( editor != null )
|
if( editor != null )
|
||||||
editor.repaint();
|
HiDPIUtils.repaint( editor );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMPONENT_ROUND_RECT:
|
case COMPONENT_ROUND_RECT:
|
||||||
case OUTLINE:
|
case OUTLINE:
|
||||||
comboBox.repaint();
|
HiDPIUtils.repaint( comboBox );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINIMUM_WIDTH:
|
case MINIMUM_WIDTH:
|
||||||
@@ -402,7 +403,7 @@ public class FlatComboBoxUI
|
|||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
comboBox.revalidate();
|
comboBox.revalidate();
|
||||||
comboBox.repaint();
|
HiDPIUtils.repaint( comboBox );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -584,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 )
|
||||||
@@ -611,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 );
|
||||||
@@ -881,7 +882,7 @@ public class FlatComboBoxUI
|
|||||||
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
||||||
if( gc != null ) {
|
if( gc != null ) {
|
||||||
Rectangle screenBounds = gc.getBounds();
|
Rectangle screenBounds = gc.getBounds();
|
||||||
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
Insets screenInsets = FlatUIUtils.getScreenInsets( gc );
|
||||||
displayWidth = Math.min( displayWidth, screenBounds.width - screenInsets.left - screenInsets.right );
|
displayWidth = Math.min( displayWidth, screenBounds.width - screenInsets.left - screenInsets.right );
|
||||||
} else {
|
} else {
|
||||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public class FlatEditorPaneUI
|
|||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle.run();
|
installStyle.run();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
@@ -32,6 +33,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.ButtonGroup;
|
import javax.swing.ButtonGroup;
|
||||||
@@ -46,6 +48,7 @@ import javax.swing.JScrollPane;
|
|||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
|
import javax.swing.Scrollable;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.filechooser.FileSystemView;
|
import javax.swing.filechooser.FileSystemView;
|
||||||
@@ -164,6 +167,7 @@ public class FlatFileChooserUI
|
|||||||
{
|
{
|
||||||
private final FlatFileView fileView = new FlatFileView();
|
private final FlatFileView fileView = new FlatFileView();
|
||||||
private FlatShortcutsPanel shortcutsPanel;
|
private FlatShortcutsPanel shortcutsPanel;
|
||||||
|
private JScrollPane shortcutsScrollPane;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatFileChooserUI( (JFileChooser) c );
|
return new FlatFileChooserUI( (JFileChooser) c );
|
||||||
@@ -183,7 +187,10 @@ public class FlatFileChooserUI
|
|||||||
FlatShortcutsPanel panel = createShortcutsPanel( fc );
|
FlatShortcutsPanel panel = createShortcutsPanel( fc );
|
||||||
if( panel.getComponentCount() > 0 ) {
|
if( panel.getComponentCount() > 0 ) {
|
||||||
shortcutsPanel = panel;
|
shortcutsPanel = panel;
|
||||||
fc.add( shortcutsPanel, BorderLayout.LINE_START );
|
shortcutsScrollPane = new JScrollPane( shortcutsPanel,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
|
||||||
|
shortcutsScrollPane.setBorder( BorderFactory.createEmptyBorder() );
|
||||||
|
fc.add( shortcutsScrollPane, BorderLayout.LINE_START );
|
||||||
fc.addPropertyChangeListener( shortcutsPanel );
|
fc.addPropertyChangeListener( shortcutsPanel );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,6 +203,7 @@ public class FlatFileChooserUI
|
|||||||
if( shortcutsPanel != null ) {
|
if( shortcutsPanel != null ) {
|
||||||
fc.removePropertyChangeListener( shortcutsPanel );
|
fc.removePropertyChangeListener( shortcutsPanel );
|
||||||
shortcutsPanel = null;
|
shortcutsPanel = null;
|
||||||
|
shortcutsScrollPane = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +332,7 @@ public class FlatFileChooserUI
|
|||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
Dimension prefSize = super.getPreferredSize( c );
|
Dimension prefSize = super.getPreferredSize( c );
|
||||||
Dimension minSize = getMinimumSize( c );
|
Dimension minSize = getMinimumSize( c );
|
||||||
int shortcutsPanelWidth = (shortcutsPanel != null) ? shortcutsPanel.getPreferredSize().width : 0;
|
int shortcutsPanelWidth = (shortcutsScrollPane != null) ? shortcutsScrollPane.getPreferredSize().width : 0;
|
||||||
return new Dimension(
|
return new Dimension(
|
||||||
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
||||||
Math.max( prefSize.height, minSize.height ) );
|
Math.max( prefSize.height, minSize.height ) );
|
||||||
@@ -368,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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,7 +446,7 @@ public class FlatFileChooserUI
|
|||||||
/** @since 2.3 */
|
/** @since 2.3 */
|
||||||
public static class FlatShortcutsPanel
|
public static class FlatShortcutsPanel
|
||||||
extends JToolBar
|
extends JToolBar
|
||||||
implements PropertyChangeListener
|
implements PropertyChangeListener, Scrollable
|
||||||
{
|
{
|
||||||
private final JFileChooser fc;
|
private final JFileChooser fc;
|
||||||
|
|
||||||
@@ -420,6 +465,7 @@ public class FlatFileChooserUI
|
|||||||
super( JToolBar.VERTICAL );
|
super( JToolBar.VERTICAL );
|
||||||
this.fc = fc;
|
this.fc = fc;
|
||||||
setFloatable( false );
|
setFloatable( false );
|
||||||
|
putClientProperty( FlatClientProperties.STYLE, "hoverButtonGroupBackground: null" );
|
||||||
|
|
||||||
buttonSize = UIScale.scale( getUIDimension( "FileChooser.shortcuts.buttonSize", 84, 64 ) );
|
buttonSize = UIScale.scale( getUIDimension( "FileChooser.shortcuts.buttonSize", 84, 64 ) );
|
||||||
iconSize = getUIDimension( "FileChooser.shortcuts.iconSize", 32, 32 );
|
iconSize = getUIDimension( "FileChooser.shortcuts.iconSize", 32, 32 );
|
||||||
@@ -461,7 +507,7 @@ public class FlatFileChooserUI
|
|||||||
icon = new ShortcutIcon( icon, iconSize.width, iconSize.height );
|
icon = new ShortcutIcon( icon, iconSize.width, iconSize.height );
|
||||||
|
|
||||||
// create button
|
// create button
|
||||||
JToggleButton button = createButton( name, icon );
|
JToggleButton button = createButton( name, icon, file.toString() );
|
||||||
File f = file;
|
File f = file;
|
||||||
button.addActionListener( e -> {
|
button.addActionListener( e -> {
|
||||||
fc.setCurrentDirectory( f );
|
fc.setCurrentDirectory( f );
|
||||||
@@ -487,8 +533,10 @@ public class FlatFileChooserUI
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JToggleButton createButton( String name, Icon icon ) {
|
/** @since 3.5 */
|
||||||
|
protected JToggleButton createButton( String name, Icon icon, String toolTip ) {
|
||||||
JToggleButton button = new JToggleButton( name, icon );
|
JToggleButton button = new JToggleButton( name, icon );
|
||||||
|
button.setToolTipText( toolTip );
|
||||||
button.setVerticalTextPosition( SwingConstants.BOTTOM );
|
button.setVerticalTextPosition( SwingConstants.BOTTOM );
|
||||||
button.setHorizontalTextPosition( SwingConstants.CENTER );
|
button.setHorizontalTextPosition( SwingConstants.CENTER );
|
||||||
button.setAlignmentX( Component.CENTER_ALIGNMENT );
|
button.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||||
@@ -566,6 +614,8 @@ public class FlatFileChooserUI
|
|||||||
buttonGroup.clearSelection();
|
buttonGroup.clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface PropertyChangeListener ----
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange( PropertyChangeEvent e ) {
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
@@ -574,6 +624,41 @@ public class FlatFileChooserUI
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface Scrollable ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredScrollableViewportSize() {
|
||||||
|
if( getComponentCount() > 0 ) {
|
||||||
|
Insets insets = getInsets();
|
||||||
|
int height = (getComponent( 0 ).getPreferredSize().height * 5) + insets.top + insets.bottom;
|
||||||
|
return new Dimension( getPreferredSize().width, height );
|
||||||
|
}
|
||||||
|
return getPreferredSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||||
|
if( orientation == SwingConstants.VERTICAL && getComponentCount() > 0 )
|
||||||
|
return getComponent( 0 ).getPreferredSize().height;
|
||||||
|
|
||||||
|
return getScrollableBlockIncrement( visibleRect, orientation, direction ) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||||
|
return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getScrollableTracksViewportWidth() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getScrollableTracksViewportHeight() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class ShortcutIcon -------------------------------------------------
|
//---- class ShortcutIcon -------------------------------------------------
|
||||||
|
|||||||
290
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
290
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JToolTip;
|
||||||
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
|
import javax.swing.text.AttributeSet;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.LabelView;
|
||||||
|
import javax.swing.text.Style;
|
||||||
|
import javax.swing.text.StyleConstants;
|
||||||
|
import javax.swing.text.View;
|
||||||
|
import javax.swing.text.html.CSS;
|
||||||
|
import javax.swing.text.html.HTMLDocument;
|
||||||
|
import javax.swing.text.html.StyleSheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public class FlatHTML
|
||||||
|
{
|
||||||
|
private FlatHTML() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds CSS rule BASE_SIZE to the style sheet of the HTML view,
|
||||||
|
* which re-calculates font sizes based on current component font size.
|
||||||
|
* This is necessary for "absolute-size" keywords (e.g. "x-large")
|
||||||
|
* for "font-size" attributes in default style sheet (see javax/swing/text/html/default.css).
|
||||||
|
* See also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values">CSS font-size</a>.
|
||||||
|
* <p>
|
||||||
|
* This method should be invoked after {@link BasicHTML#updateRenderer(JComponent, String)}.
|
||||||
|
*/
|
||||||
|
public static void updateRendererCSSFontBaseSize( JComponent c ) {
|
||||||
|
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// dumpViews( view, 0 );
|
||||||
|
|
||||||
|
Document doc = view.getDocument();
|
||||||
|
if( !(doc instanceof HTMLDocument) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add BASE_SIZE rule if necessary
|
||||||
|
// - if point size at index 7 is not 36, then probably HTML text contains BASE_SIZE rule
|
||||||
|
// - if point size at index 4 is equal to given font size, then it is not necessary to add BASE_SIZE rule
|
||||||
|
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||||
|
/*debug
|
||||||
|
for( int i = 1; i <= 7; i++ )
|
||||||
|
System.out.println( i+": "+ styleSheet.getPointSize( i ) );
|
||||||
|
debug*/
|
||||||
|
Font font = c.getFont();
|
||||||
|
if( styleSheet.getPointSize( 7 ) != 36f ||
|
||||||
|
font == null || styleSheet.getPointSize( 4 ) == font.getSize() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||||
|
if( !usesAbsoluteSizeKeywordForFontSize( view ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get HTML text from component
|
||||||
|
String text;
|
||||||
|
if( c instanceof JLabel )
|
||||||
|
text = ((JLabel)c).getText();
|
||||||
|
else if( c instanceof AbstractButton )
|
||||||
|
text = ((AbstractButton)c).getText();
|
||||||
|
else if( c instanceof JToolTip )
|
||||||
|
text = ((JToolTip)c).getTipText();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
if( text == null || !BasicHTML.isHTMLString( text ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||||
|
String style = "<style>BASE_SIZE " + font.getSize() + "</style>";
|
||||||
|
String openTag = "";
|
||||||
|
String closeTag = "";
|
||||||
|
|
||||||
|
int headIndex;
|
||||||
|
int styleIndex;
|
||||||
|
|
||||||
|
int insertIndex;
|
||||||
|
if( (headIndex = indexOfTag( text, "head", true )) >= 0 ) {
|
||||||
|
// there is a <head> tag --> insert after <head> tag
|
||||||
|
insertIndex = headIndex;
|
||||||
|
} else if( (styleIndex = indexOfTag( text, "style", false )) >= 0 ) {
|
||||||
|
// there is a <style> tag --> insert before <style> tag
|
||||||
|
insertIndex = styleIndex;
|
||||||
|
} else {
|
||||||
|
// no <head> or <style> tag --> insert <head> tag after <html> tag
|
||||||
|
insertIndex = "<html>".length();
|
||||||
|
openTag = "<head>";
|
||||||
|
closeTag = "</head>";
|
||||||
|
}
|
||||||
|
|
||||||
|
String newText = text.substring( 0, insertIndex )
|
||||||
|
+ openTag + style + closeTag
|
||||||
|
+ text.substring( insertIndex );
|
||||||
|
|
||||||
|
BasicHTML.updateRenderer( c, newText );
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large" ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||||
|
* (see javax/swing/text/html/default.css).
|
||||||
|
*/
|
||||||
|
private static boolean usesAbsoluteSizeKeywordForFontSize( View view ) {
|
||||||
|
AttributeSet attributes = view.getAttributes();
|
||||||
|
if( attributes != null ) {
|
||||||
|
Object fontSize = attributes.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||||
|
if( fontSize != null ) {
|
||||||
|
if( absoluteSizeKeywordsSet.contains( fontSize.toString() ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ ) {
|
||||||
|
if( usesAbsoluteSizeKeywordForFontSize( view.getView( i ) ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates foreground in style sheet of the HTML view.
|
||||||
|
* Adds "body { color: #<foreground-hex>; }"
|
||||||
|
*/
|
||||||
|
public static void updateRendererCSSForeground( View view, Color foreground ) {
|
||||||
|
Document doc = view.getDocument();
|
||||||
|
if( !(doc instanceof HTMLDocument) || foreground == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add foreground rule if necessary
|
||||||
|
// - use tag 'body' because BasicHTML.createHTMLView() also uses this tag
|
||||||
|
// to set font and color styles to component font/color
|
||||||
|
// see: SwingUtilities2.displayPropertiesToCSS()
|
||||||
|
// - this color is not used if component is disabled;
|
||||||
|
// JTextComponent.getDisabledTextColor() is used for disabled text components;
|
||||||
|
// UIManager.getColor("textInactiveText") is used for other disabled components
|
||||||
|
// see: javax.swing.text.GlyphView.paint()
|
||||||
|
Style bodyStyle = ((HTMLDocument)doc).getStyle( "body" );
|
||||||
|
if( bodyStyle == null ) {
|
||||||
|
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||||
|
styleSheet.addRule( String.format( "body { color: #%06x; }", foreground.getRGB() & 0xffffff ) );
|
||||||
|
clearViewCaches( view );
|
||||||
|
} else if( !foreground.equals( bodyStyle.getAttribute( StyleConstants.Foreground ) ) ) {
|
||||||
|
bodyStyle.addAttribute( StyleConstants.Foreground, foreground );
|
||||||
|
clearViewCaches( view );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears cached values in view so that CSS changes take effect.
|
||||||
|
*/
|
||||||
|
private static void clearViewCaches( View view ) {
|
||||||
|
if( view instanceof LabelView )
|
||||||
|
((LabelView)view).changedUpdate( null, null, null );
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ )
|
||||||
|
clearViewCaches( view.getView( i ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PropertyChangeListener createPropertyChangeListener( PropertyChangeListener superListener ) {
|
||||||
|
return e -> {
|
||||||
|
if( superListener != null )
|
||||||
|
superListener.propertyChange( e );
|
||||||
|
propertyChange( e );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes {@link #updateRendererCSSFontBaseSize(JComponent)}
|
||||||
|
* for {@link BasicHTML#propertyKey} property change events,
|
||||||
|
* which are fired when {@link BasicHTML#updateRenderer(JComponent, String)}
|
||||||
|
* updates the HTML view.
|
||||||
|
*/
|
||||||
|
public static void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
if( BasicHTML.propertyKey.equals( e.getPropertyName() ) && e.getNewValue() instanceof View )
|
||||||
|
updateRendererCSSFontBaseSize( (JComponent) e.getSource() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
public static void dumpView( JComponent c ) {
|
||||||
|
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null )
|
||||||
|
dumpViews( view, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpViews( View view, int indent ) {
|
||||||
|
for( int i = 0; i < indent; i++ )
|
||||||
|
System.out.print( " " );
|
||||||
|
|
||||||
|
System.out.printf( "%s @%-8x %3d,%2d",
|
||||||
|
view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName(),
|
||||||
|
System.identityHashCode( view ),
|
||||||
|
(int) view.getPreferredSpan( View.X_AXIS ),
|
||||||
|
(int) view.getPreferredSpan( View.Y_AXIS ) );
|
||||||
|
|
||||||
|
AttributeSet attrs = view.getAttributes();
|
||||||
|
if( attrs != null ) {
|
||||||
|
Object fontSize = attrs.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||||
|
System.out.printf( " %-8s", fontSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( view instanceof javax.swing.text.GlyphView ) {
|
||||||
|
javax.swing.text.GlyphView gview = ((javax.swing.text.GlyphView)view);
|
||||||
|
java.awt.Font font = gview.getFont();
|
||||||
|
System.out.printf( " %3d-%-3d %s %2d (@%x) #%06x '%s'",
|
||||||
|
gview.getStartOffset(), gview.getEndOffset() - 1,
|
||||||
|
font.getName(), font.getSize(), System.identityHashCode( font ),
|
||||||
|
gview.getForeground().getRGB() & 0xffffff,
|
||||||
|
gview.getText( gview.getStartOffset(), gview.getEndOffset() ) );
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ ) {
|
||||||
|
View child = view.getView( i );
|
||||||
|
dumpViews( child, indent + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug*/
|
||||||
|
}
|
||||||
@@ -22,11 +22,7 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
@@ -64,6 +60,9 @@ public class FlatLabelUI
|
|||||||
{
|
{
|
||||||
@Styleable protected Color disabledForeground;
|
@Styleable protected Color disabledForeground;
|
||||||
|
|
||||||
|
// only used via styling (not in UI defaults)
|
||||||
|
/** @since 3.5 */ @Styleable protected int arc = -1;
|
||||||
|
|
||||||
private final boolean shared;
|
private final boolean shared;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
@@ -110,16 +109,13 @@ public class FlatLabelUI
|
|||||||
super.installComponents( c );
|
super.installComponents( c );
|
||||||
|
|
||||||
// update HTML renderer if necessary
|
// update HTML renderer if necessary
|
||||||
updateHTMLRenderer( c, c.getText(), false );
|
FlatHTML.updateRendererCSSFontBaseSize( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange( PropertyChangeEvent e ) {
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
String name = e.getPropertyName();
|
String name = e.getPropertyName();
|
||||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) {
|
||||||
JLabel label = (JLabel) e.getSource();
|
|
||||||
updateHTMLRenderer( label, label.getText(), true );
|
|
||||||
} else if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) {
|
|
||||||
JLabel label = (JLabel) e.getSource();
|
JLabel label = (JLabel) e.getSource();
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( label ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( label ) ) {
|
||||||
// unshare component UI if necessary
|
// unshare component UI if necessary
|
||||||
@@ -128,9 +124,11 @@ public class FlatLabelUI
|
|||||||
} else
|
} else
|
||||||
installStyle( label );
|
installStyle( label );
|
||||||
label.revalidate();
|
label.revalidate();
|
||||||
label.repaint();
|
HiDPIUtils.repaint( label );
|
||||||
} else
|
}
|
||||||
super.propertyChange( e );
|
|
||||||
|
super.propertyChange( e );
|
||||||
|
FlatHTML.propertyChange( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
@@ -165,83 +163,10 @@ public class FlatLabelUI
|
|||||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Checks whether text contains HTML tags that use "absolute-size" keywords
|
public void update( Graphics g, JComponent c ) {
|
||||||
* (e.g. "x-large") for font-size in default style sheet
|
FlatPanelUI.fillRoundedBackground( g, c, arc );
|
||||||
* (see javax/swing/text/html/default.css).
|
paint( g, c );
|
||||||
* If yes, adds a special CSS rule (BASE_SIZE) to the HTML text, which
|
|
||||||
* re-calculates font sizes based on current component font size.
|
|
||||||
*/
|
|
||||||
static void updateHTMLRenderer( JComponent c, String text, boolean always ) {
|
|
||||||
if( BasicHTML.isHTMLString( text ) &&
|
|
||||||
c.getClientProperty( "html.disable" ) != Boolean.TRUE &&
|
|
||||||
needsFontBaseSize( text ) )
|
|
||||||
{
|
|
||||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
|
||||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
|
||||||
|
|
||||||
String lowerText = text.toLowerCase( Locale.ENGLISH );
|
|
||||||
int headIndex;
|
|
||||||
int styleIndex;
|
|
||||||
|
|
||||||
int insertIndex;
|
|
||||||
if( (headIndex = lowerText.indexOf( "<head>" )) >= 0 ) {
|
|
||||||
// there is a <head> tag --> insert after <head> tag
|
|
||||||
insertIndex = headIndex + "<head>".length();
|
|
||||||
} else if( (styleIndex = lowerText.indexOf( "<style>" )) >= 0 ) {
|
|
||||||
// there is a <style> tag --> insert before <style> tag
|
|
||||||
insertIndex = styleIndex;
|
|
||||||
} else {
|
|
||||||
// no <head> or <style> tag --> insert <head> tag after <html> tag
|
|
||||||
style = "<head>" + style + "</head>";
|
|
||||||
insertIndex = "<html>".length();
|
|
||||||
}
|
|
||||||
|
|
||||||
text = text.substring( 0, insertIndex )
|
|
||||||
+ style
|
|
||||||
+ text.substring( insertIndex );
|
|
||||||
} else if( !always )
|
|
||||||
return; // not necessary to invoke BasicHTML.updateRenderer()
|
|
||||||
|
|
||||||
BasicHTML.updateRenderer( c, text );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<String> tagsUseFontSizeSet;
|
|
||||||
|
|
||||||
private static boolean needsFontBaseSize( String text ) {
|
|
||||||
if( tagsUseFontSizeSet == null ) {
|
|
||||||
// tags that use font-size in javax/swing/text/html/default.css
|
|
||||||
tagsUseFontSizeSet = new HashSet<>( Arrays.asList(
|
|
||||||
"h1", "h2", "h3", "h4", "h5", "h6", "code", "kbd", "big", "small", "samp" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for tags in HTML text
|
|
||||||
int textLength = text.length();
|
|
||||||
for( int i = 6; i < textLength - 1; i++ ) {
|
|
||||||
if( text.charAt( i ) == '<' ) {
|
|
||||||
switch( text.charAt( i + 1 ) ) {
|
|
||||||
// first letters of tags in tagsUseFontSizeSet
|
|
||||||
case 'b': case 'B':
|
|
||||||
case 'c': case 'C':
|
|
||||||
case 'h': case 'H':
|
|
||||||
case 'k': case 'K':
|
|
||||||
case 's': case 'S':
|
|
||||||
int tagBegin = i + 1;
|
|
||||||
for( i += 2; i < textLength; i++ ) {
|
|
||||||
if( !Character.isLetterOrDigit( text.charAt( i ) ) ) {
|
|
||||||
String tag = text.substring( tagBegin, i ).toLowerCase( Locale.ENGLISH );
|
|
||||||
if( tagsUseFontSizeSet.contains( tag ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Graphics createGraphicsHTMLTextYCorrection( Graphics g, JComponent c ) {
|
static Graphics createGraphicsHTMLTextYCorrection( Graphics g, JComponent c ) {
|
||||||
|
|||||||
@@ -23,13 +23,20 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line border for various components.
|
* Line border for various components.
|
||||||
*
|
* <p>
|
||||||
* Paints a scaled (usually 1px thick) line around the component.
|
* Paints a scaled (usually 1px thick) line around the component.
|
||||||
* The line thickness is not added to the border insets.
|
* The line thickness is not added to the border insets.
|
||||||
* The insets should be at least have line thickness (usually 1,1,1,1).
|
* The insets should be at least have line thickness (usually 1,1,1,1).
|
||||||
|
* <p>
|
||||||
|
* For {@link javax.swing.JPanel} and {@link javax.swing.JLabel}, this border
|
||||||
|
* can be used paint rounded background (if line color is {@code null}) or
|
||||||
|
* paint rounded line border with rounded background.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
@@ -41,7 +48,7 @@ public class FlatLineBorder
|
|||||||
/** @since 2 */ private final int arc;
|
/** @since 2 */ private final int arc;
|
||||||
|
|
||||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||||
this( insets, lineColor, 1f, 0 );
|
this( insets, lineColor, 1f, -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
@@ -52,15 +59,28 @@ public class FlatLineBorder
|
|||||||
this.arc = arc;
|
this.arc = arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.5 */
|
||||||
|
public FlatLineBorder( Insets insets, int arc ) {
|
||||||
|
this( insets, null, 0, arc );
|
||||||
|
}
|
||||||
|
|
||||||
public Color getLineColor() {
|
public Color getLineColor() {
|
||||||
return lineColor;
|
return lineColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the (unscaled) line thickness used to paint the border.
|
||||||
|
* The line thickness does not affect the border insets.
|
||||||
|
*/
|
||||||
public float getLineThickness() {
|
public float getLineThickness() {
|
||||||
return lineThickness;
|
return lineThickness;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/**
|
||||||
|
* Returns the (unscaled) arc diameter of the border corners.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
public int getArc() {
|
public int getArc() {
|
||||||
return arc;
|
return arc;
|
||||||
}
|
}
|
||||||
@@ -70,11 +90,31 @@ public class FlatLineBorder
|
|||||||
if( c instanceof JComponent && ((JComponent)c).getClientProperty( FlatPopupFactory.KEY_POPUP_USES_NATIVE_BORDER ) != null )
|
if( c instanceof JComponent && ((JComponent)c).getClientProperty( FlatPopupFactory.KEY_POPUP_USES_NATIVE_BORDER ) != null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Color lineColor = getLineColor();
|
||||||
|
float lineThickness = getLineThickness();
|
||||||
|
if( lineColor == null || lineThickness <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int arc = getArc();
|
||||||
|
if( arc < 0 ) {
|
||||||
|
// get arc from label or panel
|
||||||
|
ComponentUI ui = (c instanceof JLabel)
|
||||||
|
? ((JLabel)c).getUI()
|
||||||
|
: (c instanceof JPanel ? ((JPanel)c).getUI() : null);
|
||||||
|
if( ui instanceof FlatLabelUI )
|
||||||
|
arc = ((FlatLabelUI)ui).arc;
|
||||||
|
else if( ui instanceof FlatPanelUI )
|
||||||
|
arc = ((FlatPanelUI)ui).arc;
|
||||||
|
|
||||||
|
if( arc < 0 )
|
||||||
|
arc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
0, 0, 0, scale( getLineThickness() ), scale( getArc() ), null, getLineColor(), null );
|
0, 0, 0, scale( lineThickness ), scale( arc ), null, lineColor, null );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.formdev.flatlaf.FlatClientProperties;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -56,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
|
||||||
@@ -92,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;
|
||||||
|
|
||||||
@@ -128,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" );
|
||||||
|
|
||||||
@@ -142,6 +146,7 @@ public class FlatListUI
|
|||||||
selectionForeground = null;
|
selectionForeground = null;
|
||||||
selectionInactiveBackground = null;
|
selectionInactiveBackground = null;
|
||||||
selectionInactiveForeground = null;
|
selectionInactiveForeground = null;
|
||||||
|
alternateRowColor = null;
|
||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
@@ -182,7 +187,7 @@ public class FlatListUI
|
|||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
list.revalidate();
|
list.revalidate();
|
||||||
list.repaint();
|
HiDPIUtils.repaint( list );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -205,7 +210,7 @@ public class FlatListUI
|
|||||||
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
||||||
if( r != null ) {
|
if( r != null ) {
|
||||||
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||||
list.repaint( r.x - arc, r.y - arc, r.width + (arc * 2), r.height + (arc * 2) );
|
HiDPIUtils.repaint( list, r.x - arc, r.y - arc, r.width + (arc * 2), r.height + (arc * 2) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -298,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 ) {
|
||||||
@@ -324,8 +340,7 @@ public class FlatListUI
|
|||||||
(rendererComponent instanceof DefaultListCellRenderer ||
|
(rendererComponent instanceof DefaultListCellRenderer ||
|
||||||
rendererComponent instanceof BasicComboBoxRenderer) &&
|
rendererComponent instanceof BasicComboBoxRenderer) &&
|
||||||
(selectionArc > 0 ||
|
(selectionArc > 0 ||
|
||||||
(selectionInsets != null &&
|
(selectionInsets != null && !FlatUIUtils.isInsetsEmpty( selectionInsets ))) )
|
||||||
(selectionInsets.top != 0 || selectionInsets.left != 0 || selectionInsets.bottom != 0 || selectionInsets.right != 0))) )
|
|
||||||
{
|
{
|
||||||
// Because selection painting is done in the cell renderer, it would be
|
// Because selection painting is done in the cell renderer, it would be
|
||||||
// necessary to require a FlatLaf specific renderer to implement rounded selection.
|
// necessary to require a FlatLaf specific renderer to implement rounded selection.
|
||||||
@@ -374,7 +389,15 @@ public class FlatListUI
|
|||||||
rendererPane.paintComponent( g, rendererComponent, list, cx, rowBounds.y, cw, rowBounds.height, true );
|
rendererPane.paintComponent( g, rendererComponent, list, cx, rowBounds.y, cw, rowBounds.height, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3 */
|
/**
|
||||||
|
* Paints (rounded) cell selection.
|
||||||
|
* Supports {@link #selectionArc} and {@link #selectionInsets}.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method is only invoked if either selection arc
|
||||||
|
* is greater than zero or if selection insets are not empty.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
||||||
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
@@ -440,7 +463,8 @@ public class FlatListUI
|
|||||||
* Paints a cell selection at the given coordinates.
|
* Paints a cell selection at the given coordinates.
|
||||||
* The selection color must be set on the graphics context.
|
* The selection color must be set on the graphics context.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is intended for use in custom cell renderers.
|
* This method is intended for use in custom cell renderers
|
||||||
|
* to support {@link #selectionArc} and {@link #selectionInsets}.
|
||||||
*
|
*
|
||||||
* @since 3
|
* @since 3
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ import java.awt.Font;
|
|||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.GridLayout;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
@@ -35,6 +37,7 @@ import java.util.Map;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -222,7 +225,7 @@ public class FlatMenuItemRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// arrow size
|
// arrow size
|
||||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
if( arrowIcon != null && (!isTopLevelMenu || isInVerticalMenuBar( menuItem )) ) {
|
||||||
// gap between text and arrow
|
// gap between text and arrow
|
||||||
if( accelText == null )
|
if( accelText == null )
|
||||||
width += scale( textNoAcceleratorGap );
|
width += scale( textNoAcceleratorGap );
|
||||||
@@ -254,7 +257,8 @@ public class FlatMenuItemRenderer
|
|||||||
boolean isTopLevelMenu = isTopLevelMenu( menuItem );
|
boolean isTopLevelMenu = isTopLevelMenu( menuItem );
|
||||||
|
|
||||||
// layout arrow
|
// layout arrow
|
||||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
boolean showArrowIcon = (arrowIcon != null && (!isTopLevelMenu || isInVerticalMenuBar( menuItem )));
|
||||||
|
if( showArrowIcon ) {
|
||||||
arrowRect.width = arrowIcon.getIconWidth();
|
arrowRect.width = arrowIcon.getIconWidth();
|
||||||
arrowRect.height = arrowIcon.getIconHeight();
|
arrowRect.height = arrowIcon.getIconHeight();
|
||||||
} else
|
} else
|
||||||
@@ -288,7 +292,7 @@ public class FlatMenuItemRenderer
|
|||||||
int accelArrowWidth = accelRect.width + arrowRect.width;
|
int accelArrowWidth = accelRect.width + arrowRect.width;
|
||||||
if( accelText != null )
|
if( accelText != null )
|
||||||
accelArrowWidth += scale( !isTopLevelMenu ? textAcceleratorGap : menuItem.getIconTextGap() );
|
accelArrowWidth += scale( !isTopLevelMenu ? textAcceleratorGap : menuItem.getIconTextGap() );
|
||||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
if( showArrowIcon ) {
|
||||||
if( accelText == null )
|
if( accelText == null )
|
||||||
accelArrowWidth += scale( textNoAcceleratorGap );
|
accelArrowWidth += scale( textNoAcceleratorGap );
|
||||||
accelArrowWidth += scale( acceleratorArrowGap );
|
accelArrowWidth += scale( acceleratorArrowGap );
|
||||||
@@ -355,7 +359,7 @@ debug*/
|
|||||||
paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground, selectionBackground );
|
paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground, selectionBackground );
|
||||||
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
|
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
|
||||||
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
|
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
|
||||||
if( !isTopLevelMenu( menuItem ) )
|
if( arrowIcon != null && (!isTopLevelMenu( menuItem ) || isInVerticalMenuBar( menuItem )) )
|
||||||
paintArrowIcon( g, arrowRect, arrowIcon );
|
paintArrowIcon( g, arrowRect, arrowIcon );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +524,15 @@ debug*/
|
|||||||
return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu();
|
return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.5 */
|
||||||
|
public static boolean isInVerticalMenuBar( JMenuItem menuItem ) {
|
||||||
|
if( !(menuItem instanceof JMenu) || !(menuItem.getParent() instanceof JMenuBar) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LayoutManager layout = menuItem.getParent().getLayout();
|
||||||
|
return layout instanceof GridLayout && ((GridLayout)layout).getRows() != 1;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isUnderlineSelection() {
|
protected boolean isUnderlineSelection() {
|
||||||
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,13 +103,23 @@ public class FlatMenuItemUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents( JMenuItem menuItem ) {
|
||||||
|
super.installComponents( menuItem );
|
||||||
|
|
||||||
|
// update HTML renderer if necessary
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||||
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
return FlatHTML.createPropertyChangeListener(
|
||||||
|
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||||
|
super.createPropertyChangeListener( c ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicMenuUI;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,6 +137,14 @@ public class FlatMenuUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents( JMenuItem menuItem ) {
|
||||||
|
super.installComponents( menuItem );
|
||||||
|
|
||||||
|
// update HTML renderer if necessary
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||||
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
@@ -159,7 +168,7 @@ public class FlatMenuUI
|
|||||||
JMenu menu = (JMenu) e.getSource();
|
JMenu menu = (JMenu) e.getSource();
|
||||||
if( menu.isTopLevelMenu() && menu.isRolloverEnabled() ) {
|
if( menu.isTopLevelMenu() && menu.isRolloverEnabled() ) {
|
||||||
menu.getModel().setRollover( rollover );
|
menu.getModel().setRollover( rollover );
|
||||||
menu.repaint();
|
HiDPIUtils.repaint( menu );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -167,7 +176,9 @@ public class FlatMenuUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
return FlatHTML.createPropertyChangeListener(
|
||||||
|
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||||
|
super.createPropertyChangeListener( c ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class FlatNativeLibrary
|
|||||||
|
|
||||||
String classifier;
|
String classifier;
|
||||||
String ext;
|
String ext;
|
||||||
|
boolean unknownArch = false;
|
||||||
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) {
|
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) {
|
||||||
// Windows: requires Windows 10/11 (x86, x86_64 or aarch64)
|
// Windows: requires Windows 10/11 (x86, x86_64 or aarch64)
|
||||||
|
|
||||||
@@ -90,11 +91,14 @@ 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 ) {
|
||||||
// Linux: requires x86_64
|
// Linux: x86_64 or aarch64 (but also supports unknown architectures)
|
||||||
|
|
||||||
classifier = "linux-x86_64";
|
classifier = SystemInfo.isAARCH64 ? "linux-arm64"
|
||||||
|
: (SystemInfo.isX86_64 ? "linux-x86_64"
|
||||||
|
: "linux-" + sanitize( System.getProperty( "os.arch" ) ));
|
||||||
ext = "so";
|
ext = "so";
|
||||||
|
unknownArch = !SystemInfo.isX86_64 && !SystemInfo.isAARCH64;
|
||||||
|
|
||||||
// Load libjawt.so (part of JRE) explicitly because it is not found
|
// Load libjawt.so (part of JRE) explicitly because it is not found
|
||||||
// in all Java versions/distributions.
|
// in all Java versions/distributions.
|
||||||
@@ -106,7 +110,7 @@ class FlatNativeLibrary
|
|||||||
return; // no native library available for current OS or CPU architecture
|
return; // no native library available for current OS or CPU architecture
|
||||||
|
|
||||||
// load native library
|
// load native library
|
||||||
NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext );
|
NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext, unknownArch );
|
||||||
if( !nativeLibrary.isLoaded() )
|
if( !nativeLibrary.isLoaded() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -128,7 +132,7 @@ class FlatNativeLibrary
|
|||||||
FlatNativeLibrary.nativeLibrary = nativeLibrary;
|
FlatNativeLibrary.nativeLibrary = nativeLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NativeLibrary createNativeLibrary( String classifier, String ext ) {
|
private static NativeLibrary createNativeLibrary( String classifier, String ext, boolean unknownArch ) {
|
||||||
String libraryName = "flatlaf-" + classifier;
|
String libraryName = "flatlaf-" + classifier;
|
||||||
|
|
||||||
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
|
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
|
||||||
@@ -139,9 +143,11 @@ class FlatNativeLibrary
|
|||||||
if( library.isLoaded() )
|
if( library.isLoaded() )
|
||||||
return library;
|
return library;
|
||||||
|
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName )
|
if( !unknownArch ) {
|
||||||
+ "' not found in java.library.path '" + System.getProperty( "java.library.path" )
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName )
|
||||||
+ "'. Using extracted native library instead.", null );
|
+ "' not found in java.library.path '" + System.getProperty( "java.library.path" )
|
||||||
|
+ "'. Using extracted native library instead.", null );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// try standard library naming scheme
|
// try standard library naming scheme
|
||||||
// (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives')
|
// (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives')
|
||||||
@@ -160,11 +166,13 @@ class FlatNativeLibrary
|
|||||||
return new NativeLibrary( libraryFile2, true );
|
return new NativeLibrary( libraryFile2, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '"
|
if( !unknownArch ) {
|
||||||
+ libraryFile.getName()
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '"
|
||||||
+ (libraryName2 != null ? ("' or '" + libraryName2) : "")
|
+ libraryFile.getName()
|
||||||
+ "' not found in '" + libraryFile.getParentFile().getAbsolutePath()
|
+ (libraryName2 != null ? ("' or '" + libraryName2) : "")
|
||||||
+ "'. Using extracted native library instead.", null );
|
+ "' not found in '" + libraryFile.getParentFile().getAbsolutePath()
|
||||||
|
+ "'. Using extracted native library instead.", null );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +183,7 @@ class FlatNativeLibrary
|
|||||||
return new NativeLibrary( libraryFile, true );
|
return new NativeLibrary( libraryFile, true );
|
||||||
|
|
||||||
// load from FlatLaf jar (extract native library to temp folder)
|
// load from FlatLaf jar (extract native library to temp folder)
|
||||||
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
|
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, !unknownArch );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -273,6 +281,13 @@ class FlatNativeLibrary
|
|||||||
+ '-' + classifier + '.' + ext;
|
+ '-' + classifier + '.' + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow only 'a'-'z', 'A'-'Z', '0'-'9', '_' and '-' in filenames.
|
||||||
|
*/
|
||||||
|
private static String sanitize( String s ) {
|
||||||
|
return s.replaceAll( "[^a-zA-Z0-9_-]", "_" );
|
||||||
|
}
|
||||||
|
|
||||||
private static void loadJAWT() {
|
private static void loadJAWT() {
|
||||||
try {
|
try {
|
||||||
System.loadLibrary( "jawt" );
|
System.loadLibrary( "jawt" );
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -48,8 +49,17 @@ class FlatNativeLinuxLibrary
|
|||||||
}
|
}
|
||||||
|
|
||||||
// direction for _NET_WM_MOVERESIZE message
|
// direction for _NET_WM_MOVERESIZE message
|
||||||
// see https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
|
// see https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html
|
||||||
static final int MOVE = 8;
|
static final int
|
||||||
|
SIZE_TOPLEFT = 0,
|
||||||
|
SIZE_TOP = 1,
|
||||||
|
SIZE_TOPRIGHT = 2,
|
||||||
|
SIZE_RIGHT = 3,
|
||||||
|
SIZE_BOTTOMRIGHT = 4,
|
||||||
|
SIZE_BOTTOM = 5,
|
||||||
|
SIZE_BOTTOMLEFT = 6,
|
||||||
|
SIZE_LEFT = 7,
|
||||||
|
MOVE = 8;
|
||||||
|
|
||||||
private static Boolean isXWindowSystem;
|
private static Boolean isXWindowSystem;
|
||||||
|
|
||||||
@@ -96,7 +106,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 );
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ import java.util.Map;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicPanelUI;
|
import javax.swing.plaf.basic.BasicPanelUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -110,7 +112,7 @@ public class FlatPanelUI
|
|||||||
} else
|
} else
|
||||||
installStyle( c );
|
installStyle( c );
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER:
|
case FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER:
|
||||||
@@ -160,32 +162,38 @@ public class FlatPanelUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( Graphics g, JComponent c ) {
|
public void update( Graphics g, JComponent c ) {
|
||||||
// fill background
|
fillRoundedBackground( g, c, arc );
|
||||||
if( c.isOpaque() ) {
|
paint( g, c );
|
||||||
int width = c.getWidth();
|
}
|
||||||
int height = c.getHeight();
|
|
||||||
int arc = (this.arc >= 0)
|
|
||||||
? this.arc
|
|
||||||
: ((c.getBorder() instanceof FlatLineBorder)
|
|
||||||
? ((FlatLineBorder)c.getBorder()).getArc()
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
// fill background with parent color to avoid garbage in rounded corners
|
/** @since 3.5 */
|
||||||
if( arc > 0 )
|
public static void fillRoundedBackground( Graphics g, JComponent c, int arc ) {
|
||||||
FlatUIUtils.paintParentBackground( g, c );
|
if( arc < 0 ) {
|
||||||
|
Border border = c.getBorder();
|
||||||
g.setColor( c.getBackground() );
|
arc = ((border instanceof FlatLineBorder)
|
||||||
if( arc > 0 ) {
|
? ((FlatLineBorder)border).getArc()
|
||||||
// fill rounded rectangle if having rounded corners
|
: 0);
|
||||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
|
||||||
FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, width, height,
|
|
||||||
0, UIScale.scale( arc ) );
|
|
||||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
|
||||||
} else
|
|
||||||
g.fillRect( 0, 0, width, height );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
paint( g, c );
|
// fill background
|
||||||
|
if( c.isOpaque() ) {
|
||||||
|
if( arc > 0 ) {
|
||||||
|
// fill background with parent color to avoid garbage in rounded corners
|
||||||
|
FlatUIUtils.paintParentBackground( g, c );
|
||||||
|
} else {
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill rounded rectangle if having rounded corners
|
||||||
|
if( arc > 0 ) {
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, c.getWidth(), c.getHeight(),
|
||||||
|
0, UIScale.scale( arc ) );
|
||||||
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import javax.swing.text.View;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
|
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,7 +164,7 @@ public class FlatPasswordFieldUI
|
|||||||
}
|
}
|
||||||
private void repaint( KeyEvent e ) {
|
private void repaint( KeyEvent e ) {
|
||||||
if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK ) {
|
if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK ) {
|
||||||
e.getComponent().repaint();
|
HiDPIUtils.repaint( e.getComponent() );
|
||||||
scrollCaretToVisible();
|
scrollCaretToVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +327,7 @@ public class FlatPasswordFieldUI
|
|||||||
if( visible != revealButton.isVisible() ) {
|
if( visible != revealButton.isVisible() ) {
|
||||||
revealButton.setVisible( visible );
|
revealButton.setVisible( visible );
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
|
|
||||||
if( !visible ) {
|
if( !visible ) {
|
||||||
revealButton.setSelected( false );
|
revealButton.setSelected( false );
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.AWTEvent;
|
import java.awt.AWTEvent;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
@@ -31,16 +32,19 @@ import java.awt.Panel;
|
|||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.PointerInfo;
|
import java.awt.PointerInfo;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
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;
|
||||||
import java.lang.invoke.MethodHandles;
|
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.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;
|
||||||
@@ -58,6 +62,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;
|
||||||
|
|
||||||
@@ -76,6 +81,8 @@ public class FlatPopupFactory
|
|||||||
private MethodHandle java8getPopupMethod;
|
private MethodHandle java8getPopupMethod;
|
||||||
private MethodHandle java9getPopupMethod;
|
private MethodHandle java9getPopupMethod;
|
||||||
|
|
||||||
|
private final ArrayList<NonFlashingPopup> stillShownHeavyWeightPopups = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Popup getPopup( Component owner, Component contents, int x, int y )
|
public Popup getPopup( Component owner, Component contents, int x, int y )
|
||||||
throws IllegalArgumentException
|
throws IllegalArgumentException
|
||||||
@@ -88,15 +95,28 @@ public class FlatPopupFactory
|
|||||||
|
|
||||||
fixLinuxWaylandJava21focusIssue( owner );
|
fixLinuxWaylandJava21focusIssue( owner );
|
||||||
|
|
||||||
|
// reuse a heavy weight popup window, which is still shown on screen,
|
||||||
|
// to avoid flicker when popup (e.g. tooltip) is moving while mouse is moved
|
||||||
|
for( NonFlashingPopup popup : stillShownHeavyWeightPopups ) {
|
||||||
|
if( popup.delegate != null &&
|
||||||
|
popup.owner == owner &&
|
||||||
|
(popup.contents == contents ||
|
||||||
|
(popup.contents instanceof JToolTip && contents instanceof JToolTip)) )
|
||||||
|
{
|
||||||
|
stillShownHeavyWeightPopups.remove( popup );
|
||||||
|
return reuseStillShownHeavyWeightPopups( popup, contents, x, y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
|
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
|
||||||
|
|
||||||
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
|
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
|
||||||
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), contents );
|
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
||||||
|
|
||||||
// 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 ), contents );
|
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
|
||||||
if( popup.popupWindow != null && SystemInfo.isMacOS && FlatNativeMacLibrary.isLoaded() )
|
if( popup.popupWindow != null && isMacOSBorderSupported() )
|
||||||
setupRoundedBorder( popup.popupWindow, owner, contents );
|
setupRoundedBorder( popup.popupWindow, owner, contents );
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
@@ -105,7 +125,7 @@ public class FlatPopupFactory
|
|||||||
if( isWindows11BorderSupported() &&
|
if( isWindows11BorderSupported() &&
|
||||||
getBorderCornerRadius( owner, contents ) > 0 )
|
getBorderCornerRadius( owner, contents ) > 0 )
|
||||||
{
|
{
|
||||||
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), 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.popupWindow, owner, contents );
|
||||||
return popup;
|
return popup;
|
||||||
@@ -116,7 +136,11 @@ public class FlatPopupFactory
|
|||||||
forceHeavyWeight = true;
|
forceHeavyWeight = true;
|
||||||
|
|
||||||
// create drop shadow popup
|
// create drop shadow popup
|
||||||
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
Popup popupForScreenOfOwner = getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight );
|
||||||
|
GraphicsConfiguration gc = (owner != null) ? owner.getGraphicsConfiguration() : null;
|
||||||
|
return (gc != null && gc.isTranslucencyCapable())
|
||||||
|
? new DropShadowPopup( popupForScreenOfOwner, owner, contents )
|
||||||
|
: new NonFlashingPopup( popupForScreenOfOwner, owner, contents );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,6 +251,24 @@ public class FlatPopupFactory
|
|||||||
return UIManager.get( uiKey );
|
return UIManager.get( uiKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reuse a heavy weight popup window, which is still shown on screen,
|
||||||
|
* by updating window location and contents.
|
||||||
|
* This avoid flicker when popup (e.g. a tooltip) is moving while mouse is moved.
|
||||||
|
* E.g. overridden JComponent.getToolTipLocation(MouseEvent).
|
||||||
|
* See ToolTipManager.checkForTipChange(MouseEvent).
|
||||||
|
*/
|
||||||
|
private static NonFlashingPopup reuseStillShownHeavyWeightPopups(
|
||||||
|
NonFlashingPopup reusePopup, Component contents, int ownerX, int ownerY )
|
||||||
|
{
|
||||||
|
// clone popup because PopupFactory.getPopup() should not return old instance
|
||||||
|
NonFlashingPopup popup = reusePopup.cloneForReuse();
|
||||||
|
|
||||||
|
// update popup location, size and contents
|
||||||
|
popup.reset( contents, ownerX, ownerY );
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
//---- tooltips -----------------------------------------------------------
|
//---- tooltips -----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,13 +305,13 @@ 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;
|
||||||
|
|
||||||
Rectangle screenBounds = gc.getBounds();
|
Rectangle screenBounds = gc.getBounds();
|
||||||
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
Insets screenInsets = FlatUIUtils.getScreenInsets( gc );
|
||||||
int screenTop = screenBounds.y + screenInsets.top;
|
int screenTop = screenBounds.y + screenInsets.top;
|
||||||
|
|
||||||
// place tooltip above mouse location if there is enough space
|
// place tooltip above mouse location if there is enough space
|
||||||
@@ -316,19 +358,23 @@ public class FlatPopupFactory
|
|||||||
//---- native rounded border ----------------------------------------------
|
//---- native rounded border ----------------------------------------------
|
||||||
|
|
||||||
private static boolean isWindows11BorderSupported() {
|
private static boolean isWindows11BorderSupported() {
|
||||||
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded();
|
return SystemInfo.isWindows_11_orLater &&
|
||||||
|
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
|
||||||
|
FlatNativeWindowsLibrary.isLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMacOSBorderSupported() {
|
||||||
|
return SystemInfo.isMacOS &&
|
||||||
|
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
|
||||||
|
FlatNativeMacLibrary.isLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) {
|
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) {
|
||||||
// make sure that the native window is created
|
|
||||||
if( !popupWindow.isDisplayable() )
|
|
||||||
popupWindow.addNotify();
|
|
||||||
|
|
||||||
int borderCornerRadius = getBorderCornerRadius( owner, contents );
|
int borderCornerRadius = getBorderCornerRadius( owner, contents );
|
||||||
float borderWidth = getRoundedBorderWidth( owner, contents );
|
float borderWidth = getRoundedBorderWidth( owner, contents );
|
||||||
|
|
||||||
// get Swing border color
|
// get Swing border color
|
||||||
Color borderColor = null; // use system default color
|
Color borderColor;
|
||||||
if( contents instanceof JComponent ) {
|
if( contents instanceof JComponent ) {
|
||||||
Border border = ((JComponent)contents).getBorder();
|
Border border = ((JComponent)contents).getBorder();
|
||||||
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
|
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
|
||||||
@@ -340,11 +386,33 @@ public class FlatPopupFactory
|
|||||||
borderColor = ((LineBorder)border).getLineColor();
|
borderColor = ((LineBorder)border).getLineColor();
|
||||||
else if( border instanceof EmptyBorder )
|
else if( border instanceof EmptyBorder )
|
||||||
borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
|
borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
|
||||||
|
else
|
||||||
|
borderColor = null; // use system default color
|
||||||
|
|
||||||
// avoid that FlatLineBorder paints the Swing border
|
// avoid that FlatLineBorder paints the Swing border
|
||||||
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true );
|
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true );
|
||||||
}
|
} else
|
||||||
|
borderColor = null; // use system default color
|
||||||
|
|
||||||
|
if( popupWindow.isDisplayable() ) {
|
||||||
|
// native window already created
|
||||||
|
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor );
|
||||||
|
} else {
|
||||||
|
// native window not yet created --> add listener to set native border after window creation
|
||||||
|
AtomicReference<HierarchyListener> l = new AtomicReference<>();
|
||||||
|
l.set( e -> {
|
||||||
|
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
|
||||||
|
(e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 )
|
||||||
|
{
|
||||||
|
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor );
|
||||||
|
popupWindow.removeHierarchyListener( l.get() );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
popupWindow.addHierarchyListener( l.get() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setupRoundedBorderImpl( Window popupWindow, int borderCornerRadius, float borderWidth, Color borderColor ) {
|
||||||
if( SystemInfo.isWindows ) {
|
if( SystemInfo.isWindows ) {
|
||||||
// get native window handle
|
// get native window handle
|
||||||
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
||||||
@@ -490,18 +558,31 @@ public class FlatPopupFactory
|
|||||||
|
|
||||||
//---- class NonFlashingPopup ---------------------------------------------
|
//---- class NonFlashingPopup ---------------------------------------------
|
||||||
|
|
||||||
private static class NonFlashingPopup
|
/**
|
||||||
|
* Fixes popup background flashing effect when using dark theme on light platform theme,
|
||||||
|
* where the light popup background is shown for a fraction of a second before
|
||||||
|
* the dark popup content is shown.
|
||||||
|
* This is fixed by setting popup background to content background.
|
||||||
|
* <p>
|
||||||
|
* Defers hiding of heavy weight popup window for an event cycle,
|
||||||
|
* which allows reusing popup window to avoid flicker when "moving" popup.
|
||||||
|
*/
|
||||||
|
private class NonFlashingPopup
|
||||||
extends Popup
|
extends Popup
|
||||||
{
|
{
|
||||||
private Popup delegate;
|
private Popup delegate;
|
||||||
|
Component owner;
|
||||||
private Component contents;
|
private Component contents;
|
||||||
|
|
||||||
// heavy weight
|
// heavy weight
|
||||||
protected Window popupWindow;
|
Window popupWindow;
|
||||||
private Color oldPopupWindowBackground;
|
private Color oldPopupWindowBackground;
|
||||||
|
|
||||||
NonFlashingPopup( Popup delegate, Component contents ) {
|
private boolean disposed;
|
||||||
|
|
||||||
|
NonFlashingPopup( Popup delegate, Component owner, Component contents ) {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
|
this.owner = owner;
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
|
|
||||||
popupWindow = SwingUtilities.windowForComponent( contents );
|
popupWindow = SwingUtilities.windowForComponent( contents );
|
||||||
@@ -515,10 +596,52 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NonFlashingPopup( NonFlashingPopup reusePopup ) {
|
||||||
|
delegate = reusePopup.delegate;
|
||||||
|
owner = reusePopup.owner;
|
||||||
|
contents = reusePopup.contents;
|
||||||
|
popupWindow = reusePopup.popupWindow;
|
||||||
|
oldPopupWindowBackground = reusePopup.oldPopupWindowBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonFlashingPopup cloneForReuse() {
|
||||||
|
return new NonFlashingPopup( this );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show() {
|
public final void show() {
|
||||||
|
if( disposed )
|
||||||
|
return;
|
||||||
|
|
||||||
|
showImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showImpl() {
|
||||||
if( delegate != null ) {
|
if( delegate != null ) {
|
||||||
showPopupAndFixLocation( delegate, popupWindow );
|
// On macOS and Linux, the empty popup window is shown in popup.show()
|
||||||
|
// (in peer.setVisible(true) invoked from Component.show()),
|
||||||
|
// but the popup content is painted later via repaint manager.
|
||||||
|
// This may cause some flicker, especially during JVM warm-up or
|
||||||
|
// when running JVM in interpreter mode (option -Xint).
|
||||||
|
// To reduce flicker, immediately paint popup content as soon as popup window becomes visible.
|
||||||
|
// This also fixes a problem with JetBrainsRuntime JVM, where sometimes the popups were empty.
|
||||||
|
if( (SystemInfo.isMacOS || SystemInfo.isLinux) && popupWindow instanceof JWindow ) {
|
||||||
|
HierarchyListener l = e -> {
|
||||||
|
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
|
||||||
|
(e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 )
|
||||||
|
{
|
||||||
|
((JWindow)popupWindow).getRootPane().paintImmediately(
|
||||||
|
0, 0, popupWindow.getWidth(), popupWindow.getHeight() );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
popupWindow.addHierarchyListener( l );
|
||||||
|
try {
|
||||||
|
showPopupAndFixLocation( delegate, popupWindow );
|
||||||
|
} finally {
|
||||||
|
popupWindow.removeHierarchyListener( l );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
showPopupAndFixLocation( delegate, popupWindow );
|
||||||
|
|
||||||
// increase tooltip size if necessary because it may be too small on HiDPI screens
|
// increase tooltip size if necessary because it may be too small on HiDPI screens
|
||||||
// https://bugs.openjdk.java.net/browse/JDK-8213535
|
// https://bugs.openjdk.java.net/browse/JDK-8213535
|
||||||
@@ -540,13 +663,36 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hide() {
|
public final void hide() {
|
||||||
|
if( disposed )
|
||||||
|
return;
|
||||||
|
disposed = true;
|
||||||
|
|
||||||
|
// immediately hide non-heavy weight popups or combobox popups
|
||||||
|
if( !(popupWindow instanceof JWindow) || contents instanceof BasicComboPopup ) {
|
||||||
|
hideImpl();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// defer hiding of heavy weight popup window for an event cycle,
|
||||||
|
// which allows reusing popup window to avoid flicker when "moving" popup
|
||||||
|
((JWindow)popupWindow).getContentPane().removeAll();
|
||||||
|
stillShownHeavyWeightPopups.add( this );
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
// hide popup if it was not reused
|
||||||
|
if( stillShownHeavyWeightPopups.remove( this ) )
|
||||||
|
hideImpl();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void hideImpl() {
|
||||||
if( contents instanceof JComponent )
|
if( contents instanceof JComponent )
|
||||||
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, null );
|
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, null );
|
||||||
|
|
||||||
if( delegate != null ) {
|
if( delegate != null ) {
|
||||||
delegate.hide();
|
delegate.hide();
|
||||||
delegate = null;
|
delegate = null;
|
||||||
|
owner = null;
|
||||||
contents = null;
|
contents = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,18 +700,54 @@ public class FlatPopupFactory
|
|||||||
// 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
|
||||||
popupWindow.setBackground( oldPopupWindowBackground );
|
popupWindow.setBackground( oldPopupWindowBackground );
|
||||||
|
|
||||||
|
// On macOS, popupWindow.setBackground(...) invoked from constructor,
|
||||||
|
// has no affect if the popup window peer (a NSWindow) is already created,
|
||||||
|
// which is the case when reusing a cached popup window
|
||||||
|
// (see class PopupFactory.HeavyWeightPopup).
|
||||||
|
// This may result in flicker when e.g. showing a popup in a light theme,
|
||||||
|
// then switching to a dark theme and again showing a popup,
|
||||||
|
// because the underling NSWindow still has a light background,
|
||||||
|
// which may be shown shortly before the actual dark popup content is shown.
|
||||||
|
// To fix this, dispose the popup window, which disposes the NSWindow.
|
||||||
|
// The AWT popup window stays in the popup cache, but when reusing it later,
|
||||||
|
// a new peer and a new NSWindow is created and gets the correct background.
|
||||||
|
if( SystemInfo.isMacOS )
|
||||||
|
popupWindow.dispose();
|
||||||
|
|
||||||
popupWindow = null;
|
popupWindow = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset( Component contents, int ownerX, int ownerY ) {
|
||||||
|
// update popup window location
|
||||||
|
popupWindow.setLocation( ownerX, ownerY );
|
||||||
|
|
||||||
|
// replace component in content pane
|
||||||
|
Container contentPane = ((JWindow)popupWindow).getContentPane();
|
||||||
|
contentPane.removeAll();
|
||||||
|
contentPane.add( contents, BorderLayout.CENTER );
|
||||||
|
popupWindow.pack();
|
||||||
|
|
||||||
|
// update client property on contents
|
||||||
|
if( this.contents != contents ) {
|
||||||
|
Object old = (this.contents instanceof JComponent)
|
||||||
|
? ((JComponent)this.contents).getClientProperty( KEY_POPUP_USES_NATIVE_BORDER )
|
||||||
|
: null;
|
||||||
|
if( contents instanceof JComponent )
|
||||||
|
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, old );
|
||||||
|
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class DropShadowPopup ----------------------------------------------
|
//---- class DropShadowPopup ----------------------------------------------
|
||||||
|
|
||||||
private class DropShadowPopup
|
private class DropShadowPopup
|
||||||
extends NonFlashingPopup
|
extends NonFlashingPopup
|
||||||
|
implements ComponentListener
|
||||||
{
|
{
|
||||||
private final Component owner;
|
|
||||||
|
|
||||||
// light weight
|
// light weight
|
||||||
private JComponent lightComp;
|
private JComponent lightComp;
|
||||||
private Border oldBorder;
|
private Border oldBorder;
|
||||||
@@ -580,11 +762,11 @@ public class FlatPopupFactory
|
|||||||
// heavy weight
|
// heavy weight
|
||||||
private Popup dropShadowDelegate;
|
private Popup dropShadowDelegate;
|
||||||
private Window dropShadowWindow;
|
private Window dropShadowWindow;
|
||||||
|
private JPanel dropShadowPanel2;
|
||||||
private Color oldDropShadowWindowBackground;
|
private Color oldDropShadowWindowBackground;
|
||||||
|
|
||||||
DropShadowPopup( Popup delegate, Component owner, Component contents ) {
|
DropShadowPopup( Popup delegate, Component owner, Component contents ) {
|
||||||
super( delegate, contents );
|
super( delegate, owner, contents );
|
||||||
this.owner = owner;
|
|
||||||
|
|
||||||
Dimension size = contents.getPreferredSize();
|
Dimension size = contents.getPreferredSize();
|
||||||
if( size.width <= 0 || size.height <= 0 )
|
if( size.width <= 0 || size.height <= 0 )
|
||||||
@@ -600,31 +782,31 @@ public class FlatPopupFactory
|
|||||||
// the drop shadow and is positioned behind the popup window.
|
// the drop shadow and is positioned behind the popup window.
|
||||||
|
|
||||||
// create panel that paints the drop shadow
|
// create panel that paints the drop shadow
|
||||||
JPanel dropShadowPanel = new JPanel();
|
dropShadowPanel2 = new JPanel();
|
||||||
dropShadowPanel.setBorder( createDropShadowBorder() );
|
dropShadowPanel2.setBorder( createDropShadowBorder() );
|
||||||
dropShadowPanel.setOpaque( false );
|
dropShadowPanel2.setOpaque( false );
|
||||||
|
|
||||||
// set preferred size of drop shadow panel
|
// set preferred size of drop shadow panel
|
||||||
Dimension prefSize = popupWindow.getPreferredSize();
|
Dimension prefSize = popupWindow.getPreferredSize();
|
||||||
Insets insets = dropShadowPanel.getInsets();
|
Insets insets = dropShadowPanel2.getInsets();
|
||||||
dropShadowPanel.setPreferredSize( new Dimension(
|
dropShadowPanel2.setPreferredSize( new Dimension(
|
||||||
prefSize.width + insets.left + insets.right,
|
prefSize.width + insets.left + insets.right,
|
||||||
prefSize.height + insets.top + insets.bottom ) );
|
prefSize.height + insets.top + insets.bottom ) );
|
||||||
|
|
||||||
// create heavy weight popup for drop shadow
|
// create heavy weight popup for drop shadow
|
||||||
int x = popupWindow.getX() - insets.left;
|
int x = popupWindow.getX() - insets.left;
|
||||||
int y = popupWindow.getY() - insets.top;
|
int y = popupWindow.getY() - insets.top;
|
||||||
dropShadowDelegate = getPopupForScreenOfOwner( owner, dropShadowPanel, x, y, true );
|
dropShadowDelegate = getPopupForScreenOfOwner( owner, dropShadowPanel2, x, y, true );
|
||||||
|
|
||||||
// make drop shadow popup window translucent
|
// make drop shadow popup window translucent
|
||||||
dropShadowWindow = SwingUtilities.windowForComponent( dropShadowPanel );
|
dropShadowWindow = SwingUtilities.windowForComponent( dropShadowPanel2 );
|
||||||
if( dropShadowWindow != null ) {
|
if( dropShadowWindow != null ) {
|
||||||
oldDropShadowWindowBackground = dropShadowWindow.getBackground();
|
oldDropShadowWindowBackground = dropShadowWindow.getBackground();
|
||||||
dropShadowWindow.setBackground( new Color( 0, true ) );
|
dropShadowWindow.setBackground( new Color( 0, true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 );
|
||||||
@@ -654,6 +836,23 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DropShadowPopup( DropShadowPopup reusePopup ) {
|
||||||
|
super( reusePopup );
|
||||||
|
|
||||||
|
// not necessary to clone fields used for light/medium weight popups
|
||||||
|
|
||||||
|
// heavy weight
|
||||||
|
dropShadowDelegate = reusePopup.dropShadowDelegate;
|
||||||
|
dropShadowWindow = reusePopup.dropShadowWindow;
|
||||||
|
dropShadowPanel2 = reusePopup.dropShadowPanel2;
|
||||||
|
oldDropShadowWindowBackground = reusePopup.oldDropShadowWindowBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
NonFlashingPopup cloneForReuse() {
|
||||||
|
return new DropShadowPopup( this );
|
||||||
|
}
|
||||||
|
|
||||||
private Border createDropShadowBorder() {
|
private Border createDropShadowBorder() {
|
||||||
return new FlatDropShadowBorder(
|
return new FlatDropShadowBorder(
|
||||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||||
@@ -662,14 +861,14 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show() {
|
void showImpl() {
|
||||||
if( dropShadowDelegate != null )
|
if( dropShadowDelegate != null )
|
||||||
showPopupAndFixLocation( dropShadowDelegate, dropShadowWindow );
|
showPopupAndFixLocation( dropShadowDelegate, dropShadowWindow );
|
||||||
|
|
||||||
if( mediumWeightPanel != null )
|
if( mediumWeightPanel != null )
|
||||||
showMediumWeightDropShadow();
|
showMediumWeightDropShadow();
|
||||||
|
|
||||||
super.show();
|
super.showImpl();
|
||||||
|
|
||||||
// fix location of light weight popup in case it has left or top drop shadow
|
// fix location of light weight popup in case it has left or top drop shadow
|
||||||
if( lightComp != null ) {
|
if( lightComp != null ) {
|
||||||
@@ -677,13 +876,22 @@ 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
|
||||||
public void hide() {
|
void hideImpl() {
|
||||||
|
if( popupWindow != null )
|
||||||
|
removeAllPopupWindowComponentListeners();
|
||||||
|
|
||||||
if( dropShadowDelegate != null ) {
|
if( dropShadowDelegate != null ) {
|
||||||
dropShadowDelegate.hide();
|
dropShadowDelegate.hide();
|
||||||
dropShadowDelegate = null;
|
dropShadowDelegate = null;
|
||||||
|
dropShadowPanel2 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mediumWeightPanel != null ) {
|
if( mediumWeightPanel != null ) {
|
||||||
@@ -692,7 +900,7 @@ public class FlatPopupFactory
|
|||||||
mediumWeightPanel = null;
|
mediumWeightPanel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.hide();
|
super.hideImpl();
|
||||||
|
|
||||||
if( dropShadowWindow != null ) {
|
if( dropShadowWindow != null ) {
|
||||||
dropShadowWindow.setBackground( oldDropShadowWindowBackground );
|
dropShadowWindow.setBackground( oldDropShadowWindowBackground );
|
||||||
@@ -776,5 +984,58 @@ public class FlatPopupFactory
|
|||||||
if( dropShadowPanel != null && mediumWeightPanel != null )
|
if( dropShadowPanel != null && mediumWeightPanel != null )
|
||||||
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
|
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void reset( Component contents, int ownerX, int ownerY ) {
|
||||||
|
if( popupWindow != null )
|
||||||
|
removeAllPopupWindowComponentListeners();
|
||||||
|
|
||||||
|
super.reset( contents, ownerX, ownerY );
|
||||||
|
|
||||||
|
updateDropShadowWindowBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDropShadowWindowBounds() {
|
||||||
|
if( dropShadowWindow == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 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 ) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,12 +239,14 @@ 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 = FlatUIUtils.getScreenInsets( gc );
|
||||||
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
|
||||||
return FlatUIUtils.subtractInsets( screenBounds, screenInsets );
|
return FlatUIUtils.subtractInsets( screenBounds, screenInsets );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@@ -86,6 +87,17 @@ public class FlatProgressBarUI
|
|||||||
installStyle();
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uninstallUI( JComponent c ) {
|
||||||
|
if( !EventQueue.isDispatchThread() && progressBar.isIndeterminate() ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere(
|
||||||
|
"FlatLaf: Uninstalling indeterminate progress bar UI not on AWT thread may throw NPE in FlatProgressBarUI.paint(). Use SwingUtilities.invokeLater().",
|
||||||
|
new IllegalStateException() );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.uninstallUI( c );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -110,17 +122,25 @@ public class FlatProgressBarUI
|
|||||||
|
|
||||||
propertyChangeListener = e -> {
|
propertyChangeListener = e -> {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
|
case "indeterminate":
|
||||||
|
if( !EventQueue.isDispatchThread() && !progressBar.isIndeterminate() ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere(
|
||||||
|
"FlatLaf: Using JProgressBar.setIndeterminate(false) not on AWT thread may throw NPE in FlatProgressBarUI.paint(). Use SwingUtilities.invokeLater().",
|
||||||
|
new IllegalStateException() );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PROGRESS_BAR_LARGE_HEIGHT:
|
case PROGRESS_BAR_LARGE_HEIGHT:
|
||||||
case PROGRESS_BAR_SQUARE:
|
case PROGRESS_BAR_SQUARE:
|
||||||
progressBar.revalidate();
|
progressBar.revalidate();
|
||||||
progressBar.repaint();
|
HiDPIUtils.repaint( progressBar );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STYLE:
|
case STYLE:
|
||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
progressBar.revalidate();
|
progressBar.revalidate();
|
||||||
progressBar.repaint();
|
HiDPIUtils.repaint( progressBar );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -274,6 +294,6 @@ public class FlatProgressBarUI
|
|||||||
// Only solution is to repaint whole progress bar.
|
// Only solution is to repaint whole progress bar.
|
||||||
double systemScaleFactor = UIScale.getSystemScaleFactor( progressBar.getGraphicsConfiguration() );
|
double systemScaleFactor = UIScale.getSystemScaleFactor( progressBar.getGraphicsConfiguration() );
|
||||||
if( (int) systemScaleFactor != systemScaleFactor )
|
if( (int) systemScaleFactor != systemScaleFactor )
|
||||||
progressBar.repaint();
|
HiDPIUtils.repaint( progressBar );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.lang.invoke.MethodHandles;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
@@ -102,13 +103,23 @@ public class FlatRadioButtonMenuItemUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents( JMenuItem menuItem ) {
|
||||||
|
super.installComponents( menuItem );
|
||||||
|
|
||||||
|
// update HTML renderer if necessary
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||||
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
return FlatHTML.createPropertyChangeListener(
|
||||||
|
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||||
|
super.createPropertyChangeListener( c ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.plaf.basic.BasicRadioButtonUI;
|
import javax.swing.plaf.basic.BasicRadioButtonUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
|
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -159,6 +161,10 @@ public class FlatRadioButtonUI
|
|||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
|
case BasicHTML.propertyKey:
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( b );
|
||||||
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.STYLE:
|
case FlatClientProperties.STYLE:
|
||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||||
@@ -168,7 +174,7 @@ public class FlatRadioButtonUI
|
|||||||
} else
|
} else
|
||||||
installStyle( b );
|
installStyle( b );
|
||||||
b.revalidate();
|
b.revalidate();
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import java.awt.Window;
|
|||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
@@ -448,6 +449,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() );
|
||||||
@@ -480,8 +486,12 @@ public class FlatRootPaneUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "ancestor":
|
case "ancestor":
|
||||||
if( e.getNewValue() instanceof Window )
|
if( e.getNewValue() instanceof Window ) {
|
||||||
|
if( titlePane != null && !Objects.equals( titlePane.windowStyle, FlatTitlePane.getWindowStyle( rootPane ) ) )
|
||||||
|
setTitlePane( createTitlePane() );
|
||||||
|
|
||||||
macClearBackgroundForTranslucentWindow( rootPane );
|
macClearBackgroundForTranslucentWindow( rootPane );
|
||||||
|
}
|
||||||
|
|
||||||
macUninstallWindowBackgroundListener( rootPane );
|
macUninstallWindowBackgroundListener( rootPane );
|
||||||
macInstallWindowBackgroundListener( rootPane );
|
macInstallWindowBackgroundListener( rootPane );
|
||||||
@@ -679,7 +689,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 +722,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 ) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -212,14 +213,14 @@ public class FlatScrollBarUI
|
|||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
case FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS:
|
case FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS:
|
||||||
scrollbar.revalidate();
|
scrollbar.revalidate();
|
||||||
scrollbar.repaint();
|
HiDPIUtils.repaint( scrollbar );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.STYLE:
|
case FlatClientProperties.STYLE:
|
||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
scrollbar.revalidate();
|
scrollbar.revalidate();
|
||||||
scrollbar.repaint();
|
HiDPIUtils.repaint( scrollbar );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "componentOrientation":
|
case "componentOrientation":
|
||||||
@@ -492,7 +493,7 @@ public class FlatScrollBarUI
|
|||||||
|
|
||||||
private void repaint() {
|
private void repaint() {
|
||||||
if( scrollbar.isEnabled() )
|
if( scrollbar.isEnabled() )
|
||||||
scrollbar.repaint();
|
HiDPIUtils.repaint( scrollbar );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import javax.swing.plaf.basic.BasicScrollPaneUI;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -209,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 ) {
|
||||||
@@ -297,11 +298,11 @@ public class FlatScrollPaneUI
|
|||||||
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
|
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
|
||||||
if( vsb != null ) {
|
if( vsb != null ) {
|
||||||
vsb.revalidate();
|
vsb.revalidate();
|
||||||
vsb.repaint();
|
HiDPIUtils.repaint( vsb );
|
||||||
}
|
}
|
||||||
if( hsb != null ) {
|
if( hsb != null ) {
|
||||||
hsb.revalidate();
|
hsb.revalidate();
|
||||||
hsb.repaint();
|
HiDPIUtils.repaint( hsb );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -321,14 +322,14 @@ public class FlatScrollPaneUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.OUTLINE:
|
case FlatClientProperties.OUTLINE:
|
||||||
scrollpane.repaint();
|
HiDPIUtils.repaint( scrollpane );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.STYLE:
|
case FlatClientProperties.STYLE:
|
||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
scrollpane.revalidate();
|
scrollpane.revalidate();
|
||||||
scrollpane.repaint();
|
HiDPIUtils.repaint( scrollpane );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "border":
|
case "border":
|
||||||
@@ -339,7 +340,7 @@ public class FlatScrollPaneUI
|
|||||||
borderShared = null;
|
borderShared = null;
|
||||||
installStyle();
|
installStyle();
|
||||||
scrollpane.revalidate();
|
scrollpane.revalidate();
|
||||||
scrollpane.repaint();
|
HiDPIUtils.repaint( scrollpane );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -538,14 +539,14 @@ public class FlatScrollPaneUI
|
|||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
if( scrollpane.getBorder() instanceof FlatBorder )
|
if( scrollpane.getBorder() instanceof FlatBorder )
|
||||||
scrollpane.repaint();
|
HiDPIUtils.repaint( scrollpane );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
if( scrollpane.getBorder() instanceof FlatBorder )
|
if( scrollpane.getBorder() instanceof FlatBorder )
|
||||||
scrollpane.repaint();
|
HiDPIUtils.repaint( scrollpane );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import javax.swing.plaf.basic.BasicSeparatorUI;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +135,7 @@ public class FlatSeparatorUI
|
|||||||
} else
|
} else
|
||||||
installStyle( s );
|
installStyle( s );
|
||||||
s.revalidate();
|
s.revalidate();
|
||||||
s.repaint();
|
HiDPIUtils.repaint( s );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
|
import java.awt.event.FocusListener;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
@@ -191,6 +193,23 @@ public class FlatSliderUI
|
|||||||
return new FlatTrackListener();
|
return new FlatTrackListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FocusListener createFocusListener( JSlider slider ) {
|
||||||
|
return new BasicSliderUI.FocusHandler() {
|
||||||
|
@Override
|
||||||
|
public void focusGained( FocusEvent e ) {
|
||||||
|
super.focusGained( e );
|
||||||
|
HiDPIUtils.repaint( slider );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost( FocusEvent e ) {
|
||||||
|
super.focusLost( e );
|
||||||
|
HiDPIUtils.repaint( slider );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener( JSlider slider ) {
|
protected PropertyChangeListener createPropertyChangeListener( JSlider slider ) {
|
||||||
return FlatStylingSupport.createPropertyChangeListener( slider, this::installStyle,
|
return FlatStylingSupport.createPropertyChangeListener( slider, this::installStyle,
|
||||||
@@ -422,7 +441,7 @@ debug*/
|
|||||||
Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, int focusWidth )
|
Color thumbColor, Color thumbBorderColor, Color focusedColor, float thumbBorderWidth, int focusWidth )
|
||||||
{
|
{
|
||||||
double systemScaleFactor = UIScale.getSystemScaleFactor( (Graphics2D) g );
|
double systemScaleFactor = UIScale.getSystemScaleFactor( (Graphics2D) g );
|
||||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
if( systemScaleFactor != (int) systemScaleFactor ) {
|
||||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height,
|
HiDPIUtils.paintAtScale1x( (Graphics2D) g, thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height,
|
||||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
@@ -579,15 +598,15 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setThumbLocation( int x, int y ) {
|
public void setThumbLocation( int x, int y ) {
|
||||||
|
// set new thumb location and compute union of old and new thumb bounds
|
||||||
|
Rectangle r = new Rectangle( thumbRect );
|
||||||
|
thumbRect.setLocation( x, y );
|
||||||
|
SwingUtilities.computeUnion( thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, r );
|
||||||
|
|
||||||
if( !isRoundThumb() ) {
|
if( !isRoundThumb() ) {
|
||||||
// the needle of the directional thumb is painted outside of thumbRect
|
// the needle of the directional thumb is painted outside of thumbRect
|
||||||
// --> must increase repaint rectangle
|
// --> must increase repaint rectangle
|
||||||
|
|
||||||
// set new thumb location and compute union of old and new thumb bounds
|
|
||||||
Rectangle r = new Rectangle( thumbRect );
|
|
||||||
thumbRect.setLocation( x, y );
|
|
||||||
SwingUtilities.computeUnion( thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, r );
|
|
||||||
|
|
||||||
// increase union rectangle for repaint
|
// increase union rectangle for repaint
|
||||||
int extra = (int) Math.ceil( UIScale.scale( focusWidth ) * 0.4142f );
|
int extra = (int) Math.ceil( UIScale.scale( focusWidth ) * 0.4142f );
|
||||||
if( slider.getOrientation() == JSlider.HORIZONTAL )
|
if( slider.getOrientation() == JSlider.HORIZONTAL )
|
||||||
@@ -597,10 +616,9 @@ debug*/
|
|||||||
if( !slider.getComponentOrientation().isLeftToRight() )
|
if( !slider.getComponentOrientation().isLeftToRight() )
|
||||||
r.x -= extra;
|
r.x -= extra;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
slider.repaint( r );
|
HiDPIUtils.repaint( slider, r );
|
||||||
} else
|
|
||||||
super.setThumbLocation( x, y );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatTrackListener --------------------------------------------
|
//---- class FlatTrackListener --------------------------------------------
|
||||||
@@ -688,21 +706,21 @@ debug*/
|
|||||||
!UIManager.getBoolean( "Slider.snapToTicksOnReleased" ) )
|
!UIManager.getBoolean( "Slider.snapToTicksOnReleased" ) )
|
||||||
{
|
{
|
||||||
calculateThumbLocation();
|
calculateThumbLocation();
|
||||||
slider.repaint();
|
HiDPIUtils.repaint( slider );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setThumbHover( boolean hover ) {
|
protected void setThumbHover( boolean hover ) {
|
||||||
if( hover != thumbHover ) {
|
if( hover != thumbHover ) {
|
||||||
thumbHover = hover;
|
thumbHover = hover;
|
||||||
slider.repaint( thumbRect );
|
HiDPIUtils.repaint( slider, thumbRect );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setThumbPressed( boolean pressed ) {
|
protected void setThumbPressed( boolean pressed ) {
|
||||||
if( pressed != thumbPressed ) {
|
if( pressed != thumbPressed ) {
|
||||||
thumbPressed = pressed;
|
thumbPressed = pressed;
|
||||||
slider.repaint( thumbRect );
|
HiDPIUtils.repaint( slider, thumbRect );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicSpinnerUI;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,8 +140,6 @@ public class FlatSpinnerUI
|
|||||||
buttonHoverArrowColor = UIManager.getColor( "Spinner.buttonHoverArrowColor" );
|
buttonHoverArrowColor = UIManager.getColor( "Spinner.buttonHoverArrowColor" );
|
||||||
buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" );
|
buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" );
|
||||||
padding = UIManager.getInsets( "Spinner.padding" );
|
padding = UIManager.getInsets( "Spinner.padding" );
|
||||||
|
|
||||||
MigLayoutVisualPadding.install( spinner );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -161,8 +160,6 @@ public class FlatSpinnerUI
|
|||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
borderShared = null;
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( spinner );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -172,6 +169,8 @@ public class FlatSpinnerUI
|
|||||||
addEditorFocusListener( spinner.getEditor() );
|
addEditorFocusListener( spinner.getEditor() );
|
||||||
spinner.addFocusListener( getHandler() );
|
spinner.addFocusListener( getHandler() );
|
||||||
spinner.addPropertyChangeListener( getHandler() );
|
spinner.addPropertyChangeListener( getHandler() );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.install( spinner );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,6 +182,8 @@ public class FlatSpinnerUI
|
|||||||
spinner.removePropertyChangeListener( getHandler() );
|
spinner.removePropertyChangeListener( getHandler() );
|
||||||
|
|
||||||
handler = null;
|
handler = null;
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.uninstall( spinner );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Handler getHandler() {
|
private Handler getHandler() {
|
||||||
@@ -586,7 +587,7 @@ public class FlatSpinnerUI
|
|||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
spinner.repaint();
|
HiDPIUtils.repaint( spinner );
|
||||||
|
|
||||||
// if spinner gained focus, transfer it to the editor text field
|
// if spinner gained focus, transfer it to the editor text field
|
||||||
if( e.getComponent() == spinner ) {
|
if( e.getComponent() == spinner ) {
|
||||||
@@ -599,7 +600,7 @@ public class FlatSpinnerUI
|
|||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
spinner.repaint();
|
HiDPIUtils.repaint( spinner );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- interface PropertyChangeListener ----
|
//---- interface PropertyChangeListener ----
|
||||||
@@ -614,7 +615,7 @@ public class FlatSpinnerUI
|
|||||||
|
|
||||||
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
||||||
case FlatClientProperties.OUTLINE:
|
case FlatClientProperties.OUTLINE:
|
||||||
spinner.repaint();
|
HiDPIUtils.repaint( spinner );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.MINIMUM_WIDTH:
|
case FlatClientProperties.MINIMUM_WIDTH:
|
||||||
@@ -625,7 +626,7 @@ public class FlatSpinnerUI
|
|||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
spinner.revalidate();
|
spinner.revalidate();
|
||||||
spinner.repaint();
|
HiDPIUtils.repaint( spinner );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for styling components in CSS syntax.
|
* Support for styling components in CSS syntax.
|
||||||
@@ -324,22 +324,24 @@ public class FlatStylingSupport
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
Map<String, Object> oldValues = new HashMap<>();
|
Map<String, Object> oldValues = new HashMap<>();
|
||||||
|
outer:
|
||||||
for( Map.Entry<String, Object> e : style.entrySet() ) {
|
for( Map.Entry<String, Object> e : style.entrySet() ) {
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
Object newValue = e.getValue();
|
Object newValue = e.getValue();
|
||||||
|
|
||||||
// handle key prefix
|
// handle key prefix
|
||||||
if( key.startsWith( "[" ) ) {
|
while( key.startsWith( "[" ) ) {
|
||||||
if( (SystemInfo.isWindows && key.startsWith( "[win]" )) ||
|
int closeIndex = key.indexOf( ']' );
|
||||||
(SystemInfo.isMacOS && key.startsWith( "[mac]" )) ||
|
if( closeIndex < 0 )
|
||||||
(SystemInfo.isLinux && key.startsWith( "[linux]" )) ||
|
continue outer;
|
||||||
(key.startsWith( "[light]" ) && !FlatLaf.isLafDark()) ||
|
|
||||||
(key.startsWith( "[dark]" ) && FlatLaf.isLafDark()) )
|
String prefix = key.substring( 0, closeIndex + 1 );
|
||||||
{
|
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( FlatLaf.isLafDark() );
|
||||||
// prefix is known and enabled --> remove prefix
|
if( !lightOrDarkPrefix.equals( prefix ) && !FlatLaf.getUIKeyPlatformPrefixes().contains( prefix ) )
|
||||||
key = key.substring( key.indexOf( ']' ) + 1 );
|
continue outer;
|
||||||
} else
|
|
||||||
continue;
|
// prefix is known and enabled --> remove prefix
|
||||||
|
key = key.substring( closeIndex + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
Object oldValue = applyProperty.apply( key, newValue );
|
Object oldValue = applyProperty.apply( key, newValue );
|
||||||
@@ -709,7 +711,7 @@ public class FlatStylingSupport
|
|||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle.run();
|
installStyle.run();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
|||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
import com.formdev.flatlaf.util.Animator;
|
import com.formdev.flatlaf.util.Animator;
|
||||||
import com.formdev.flatlaf.util.CubicBezierEasing;
|
import com.formdev.flatlaf.util.CubicBezierEasing;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.JavaCompatibility;
|
import com.formdev.flatlaf.util.JavaCompatibility;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
@@ -895,7 +896,7 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tabPane.repaint( r );
|
HiDPIUtils.repaint( tabPane, r );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean inCalculateEqual;
|
private boolean inCalculateEqual;
|
||||||
@@ -1684,7 +1685,7 @@ debug*/
|
|||||||
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
|
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
|
||||||
|
|
||||||
// add gap for selected tab to path
|
// add gap for selected tab to path
|
||||||
if( getTabType() == TAB_TYPE_CARD ) {
|
if( getTabType() == TAB_TYPE_CARD && selectedIndex >= 0 ) {
|
||||||
float csh = scale( (float) contentSeparatorHeight );
|
float csh = scale( (float) contentSeparatorHeight );
|
||||||
|
|
||||||
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
|
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
|
||||||
@@ -2305,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
|
||||||
}
|
}
|
||||||
@@ -2581,19 +2597,19 @@ debug*/
|
|||||||
@Override
|
@Override
|
||||||
public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {
|
public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {
|
||||||
popupVisible = true;
|
popupVisible = true;
|
||||||
repaint();
|
HiDPIUtils.repaint( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
|
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
|
||||||
popupVisible = false;
|
popupVisible = false;
|
||||||
repaint();
|
HiDPIUtils.repaint( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void popupMenuCanceled( PopupMenuEvent e ) {
|
public void popupMenuCanceled( PopupMenuEvent e ) {
|
||||||
popupVisible = false;
|
popupVisible = false;
|
||||||
repaint();
|
HiDPIUtils.repaint( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3102,7 +3118,7 @@ debug*/
|
|||||||
|
|
||||||
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
||||||
case TABBED_PANE_TAB_TYPE:
|
case TABBED_PANE_TAB_TYPE:
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
||||||
@@ -3125,14 +3141,14 @@ debug*/
|
|||||||
case TABBED_PANE_TAB_ICON_PLACEMENT:
|
case TABBED_PANE_TAB_ICON_PLACEMENT:
|
||||||
case TABBED_PANE_TAB_CLOSABLE:
|
case TABBED_PANE_TAB_CLOSABLE:
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TABBED_PANE_LEADING_COMPONENT:
|
case TABBED_PANE_LEADING_COMPONENT:
|
||||||
uninstallLeadingComponent();
|
uninstallLeadingComponent();
|
||||||
installLeadingComponent();
|
installLeadingComponent();
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
ensureSelectedTabIsVisibleLater();
|
ensureSelectedTabIsVisibleLater();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3140,7 +3156,7 @@ debug*/
|
|||||||
uninstallTrailingComponent();
|
uninstallTrailingComponent();
|
||||||
installTrailingComponent();
|
installTrailingComponent();
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
ensureSelectedTabIsVisibleLater();
|
ensureSelectedTabIsVisibleLater();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3148,7 +3164,7 @@ debug*/
|
|||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3172,7 +3188,7 @@ debug*/
|
|||||||
case TABBED_PANE_TAB_ALIGNMENT:
|
case TABBED_PANE_TAB_ALIGNMENT:
|
||||||
case TABBED_PANE_TAB_CLOSABLE:
|
case TABBED_PANE_TAB_CLOSABLE:
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
HiDPIUtils.repaint( tabPane );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,8 +65,28 @@ public class FlatTableCellBorder
|
|||||||
return super.getLineColor();
|
return super.getLineColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getArc() {
|
||||||
|
if( c != null ) {
|
||||||
|
Integer selectionArc = getStyleFromTableUI( c, ui -> ui.selectionArc );
|
||||||
|
if( selectionArc != null )
|
||||||
|
return selectionArc;
|
||||||
|
}
|
||||||
|
return super.getArc();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
if( c != null ) {
|
||||||
|
Insets selectionInsets = getStyleFromTableUI( c, ui -> ui.selectionInsets );
|
||||||
|
if( selectionInsets != null ) {
|
||||||
|
x += selectionInsets.left;
|
||||||
|
y += selectionInsets.top;
|
||||||
|
width -= selectionInsets.left + selectionInsets.right;
|
||||||
|
height -= selectionInsets.top + selectionInsets.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.c = c;
|
this.c = c;
|
||||||
super.paintBorder( c, g, x, y, width, height );
|
super.paintBorder( c, g, x, y, width, height );
|
||||||
this.c = null;
|
this.c = null;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import javax.swing.table.TableColumn;
|
|||||||
import javax.swing.table.TableColumnModel;
|
import javax.swing.table.TableColumnModel;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -234,8 +235,8 @@ public class FlatTableHeaderUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void rolloverColumnUpdated( int oldColumn, int newColumn ) {
|
protected void rolloverColumnUpdated( int oldColumn, int newColumn ) {
|
||||||
header.repaint( header.getHeaderRect( oldColumn ) );
|
HiDPIUtils.repaint( header, header.getHeaderRect( oldColumn ) );
|
||||||
header.repaint( header.getHeaderRect( newColumn ) );
|
HiDPIUtils.repaint( header, header.getHeaderRect( newColumn ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,7 +24,13 @@ import java.awt.EventQueue;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Shape;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.ComponentListener;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
@@ -33,26 +39,35 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.JViewport;
|
import javax.swing.JViewport;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import javax.swing.event.TableColumnModelEvent;
|
||||||
|
import javax.swing.event.TableColumnModelListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicTableUI;
|
import javax.swing.plaf.basic.BasicTableUI;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
import javax.swing.table.JTableHeader;
|
import javax.swing.table.JTableHeader;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
import javax.swing.table.TableColumnModel;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
|
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -92,6 +107,8 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Table.intercellSpacing Dimension
|
* @uiDefault Table.intercellSpacing Dimension
|
||||||
* @uiDefault Table.selectionInactiveBackground Color
|
* @uiDefault Table.selectionInactiveBackground Color
|
||||||
* @uiDefault Table.selectionInactiveForeground Color
|
* @uiDefault Table.selectionInactiveForeground Color
|
||||||
|
* @uiDefault Table.selectionInsets Insets
|
||||||
|
* @uiDefault Table.selectionArc int
|
||||||
* @uiDefault Table.paintOutsideAlternateRows boolean
|
* @uiDefault Table.paintOutsideAlternateRows boolean
|
||||||
* @uiDefault Table.editorSelectAllOnStartEditing boolean
|
* @uiDefault Table.editorSelectAllOnStartEditing boolean
|
||||||
*
|
*
|
||||||
@@ -120,6 +137,8 @@ public class FlatTableUI
|
|||||||
@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.5 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3.5 */ @Styleable protected int selectionArc;
|
||||||
|
|
||||||
// for FlatTableCellBorder
|
// for FlatTableCellBorder
|
||||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||||
@@ -132,6 +151,9 @@ public class FlatTableUI
|
|||||||
private TableCellRenderer oldBooleanRenderer;
|
private TableCellRenderer oldBooleanRenderer;
|
||||||
|
|
||||||
private PropertyChangeListener propertyChangeListener;
|
private PropertyChangeListener propertyChangeListener;
|
||||||
|
private ComponentListener outsideAlternateRowsListener;
|
||||||
|
private ListSelectionListener rowSelectionListener;
|
||||||
|
private TableColumnModelListener columnSelectionListener;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
@@ -158,6 +180,8 @@ public class FlatTableUI
|
|||||||
selectionForeground = UIManager.getColor( "Table.selectionForeground" );
|
selectionForeground = UIManager.getColor( "Table.selectionForeground" );
|
||||||
selectionInactiveBackground = UIManager.getColor( "Table.selectionInactiveBackground" );
|
selectionInactiveBackground = UIManager.getColor( "Table.selectionInactiveBackground" );
|
||||||
selectionInactiveForeground = UIManager.getColor( "Table.selectionInactiveForeground" );
|
selectionInactiveForeground = UIManager.getColor( "Table.selectionInactiveForeground" );
|
||||||
|
selectionInsets = UIManager.getInsets( "Table.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "Table.selectionArc" );
|
||||||
|
|
||||||
toggleSelectionColors();
|
toggleSelectionColors();
|
||||||
|
|
||||||
@@ -245,6 +269,28 @@ public class FlatTableUI
|
|||||||
|
|
||||||
propertyChangeListener = e -> {
|
propertyChangeListener = e -> {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
|
case "selectionModel":
|
||||||
|
if( rowSelectionListener != null ) {
|
||||||
|
Object oldModel = e.getOldValue();
|
||||||
|
Object newModel = e.getNewValue();
|
||||||
|
if( oldModel != null )
|
||||||
|
((ListSelectionModel)oldModel).removeListSelectionListener( rowSelectionListener );
|
||||||
|
if( newModel != null )
|
||||||
|
((ListSelectionModel)newModel).addListSelectionListener( rowSelectionListener );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "columnModel":
|
||||||
|
if( columnSelectionListener != null ) {
|
||||||
|
Object oldModel = e.getOldValue();
|
||||||
|
Object newModel = e.getNewValue();
|
||||||
|
if( oldModel != null )
|
||||||
|
((TableColumnModel)oldModel).removeColumnModelListener( columnSelectionListener );
|
||||||
|
if( newModel != null )
|
||||||
|
((TableColumnModel)newModel).addColumnModelListener( columnSelectionListener );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.COMPONENT_FOCUS_OWNER:
|
case FlatClientProperties.COMPONENT_FOCUS_OWNER:
|
||||||
toggleSelectionColors();
|
toggleSelectionColors();
|
||||||
break;
|
break;
|
||||||
@@ -253,11 +299,14 @@ public class FlatTableUI
|
|||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
table.revalidate();
|
table.revalidate();
|
||||||
table.repaint();
|
HiDPIUtils.repaint( table );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
table.addPropertyChangeListener( propertyChangeListener );
|
table.addPropertyChangeListener( propertyChangeListener );
|
||||||
|
|
||||||
|
if( selectionArc > 0 )
|
||||||
|
installRepaintRoundedSelectionListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -266,6 +315,19 @@ public class FlatTableUI
|
|||||||
|
|
||||||
table.removePropertyChangeListener( propertyChangeListener );
|
table.removePropertyChangeListener( propertyChangeListener );
|
||||||
propertyChangeListener = null;
|
propertyChangeListener = null;
|
||||||
|
|
||||||
|
if( outsideAlternateRowsListener != null ) {
|
||||||
|
table.removeComponentListener( outsideAlternateRowsListener );
|
||||||
|
outsideAlternateRowsListener = null;
|
||||||
|
}
|
||||||
|
if( rowSelectionListener != null ) {
|
||||||
|
table.getSelectionModel().removeListSelectionListener( rowSelectionListener );
|
||||||
|
rowSelectionListener = null;
|
||||||
|
}
|
||||||
|
if( columnSelectionListener != null ) {
|
||||||
|
table.getColumnModel().removeColumnModelListener( columnSelectionListener );
|
||||||
|
columnSelectionListener = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -342,6 +404,8 @@ public class FlatTableUI
|
|||||||
protected Object applyStyleProperty( String key, Object value ) {
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
if( "rowHeight".equals( key ) && value instanceof Integer )
|
if( "rowHeight".equals( key ) && value instanceof Integer )
|
||||||
value = UIScale.scale( (Integer) value );
|
value = UIScale.scale( (Integer) value );
|
||||||
|
else if( "selectionArc".equals( key ) && value instanceof Integer && (Integer) value > 0 )
|
||||||
|
installRepaintRoundedSelectionListeners();
|
||||||
|
|
||||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, table, key, value );
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, table, key, value );
|
||||||
}
|
}
|
||||||
@@ -404,6 +468,7 @@ public class FlatTableUI
|
|||||||
|
|
||||||
double systemScaleFactor = UIScale.getSystemScaleFactor( (Graphics2D) g );
|
double systemScaleFactor = UIScale.getSystemScaleFactor( (Graphics2D) g );
|
||||||
double lineThickness = (1. / systemScaleFactor) * (int) systemScaleFactor;
|
double lineThickness = (1. / systemScaleFactor) * (int) systemScaleFactor;
|
||||||
|
double lineOffset = (1. - lineThickness) + 0.05; // adding 0.05 to fix line location in some cases
|
||||||
|
|
||||||
// Java 8 uses drawLine() to paint grid lines
|
// Java 8 uses drawLine() to paint grid lines
|
||||||
// Java 9+ uses fillRect() to paint grid lines (except for dragged column)
|
// Java 9+ uses fillRect() to paint grid lines (except for dragged column)
|
||||||
@@ -446,11 +511,11 @@ public class FlatTableUI
|
|||||||
// reduce line thickness to avoid unstable painted line thickness
|
// reduce line thickness to avoid unstable painted line thickness
|
||||||
if( lineThickness != 1 ) {
|
if( lineThickness != 1 ) {
|
||||||
if( horizontalLines && height == 1 && wasInvokedFromPaintGrid() ) {
|
if( horizontalLines && height == 1 && wasInvokedFromPaintGrid() ) {
|
||||||
super.fill( new Rectangle2D.Double( x, y, width, lineThickness ) );
|
super.fill( new Rectangle2D.Double( x, y + lineOffset, width, lineThickness ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( verticalLines && width == 1 && y == 0 && wasInvokedFromPaintGrid() ) {
|
if( verticalLines && width == 1 && y == 0 && wasInvokedFromPaintGrid() ) {
|
||||||
super.fill( new Rectangle2D.Double( x, y, lineThickness, height ) );
|
super.fill( new Rectangle2D.Double( x + lineOffset, y, lineThickness, height ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,6 +533,10 @@ public class FlatTableUI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rounded selection or selection insets
|
||||||
|
if( selectionArc > 0 || (selectionInsets != null && !FlatUIUtils.isInsetsEmpty( selectionInsets )) )
|
||||||
|
g = new RoundedSelectionGraphics( g, UIManager.getColor( "Table.alternateRowColor" ) );
|
||||||
|
|
||||||
super.paint( g, c );
|
super.paint( g, c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,8 +582,6 @@ public class FlatTableUI
|
|||||||
boolean paintOutside = UIManager.getBoolean( "Table.paintOutsideAlternateRows" );
|
boolean paintOutside = UIManager.getBoolean( "Table.paintOutsideAlternateRows" );
|
||||||
Color alternateColor;
|
Color alternateColor;
|
||||||
if( paintOutside && (alternateColor = UIManager.getColor( "Table.alternateRowColor" )) != null ) {
|
if( paintOutside && (alternateColor = UIManager.getColor( "Table.alternateRowColor" )) != null ) {
|
||||||
g.setColor( alternateColor );
|
|
||||||
|
|
||||||
int rowCount = table.getRowCount();
|
int rowCount = table.getRowCount();
|
||||||
|
|
||||||
// paint alternating empty rows below the table
|
// paint alternating empty rows below the table
|
||||||
@@ -523,10 +590,350 @@ public class FlatTableUI
|
|||||||
int tableWidth = table.getWidth();
|
int tableWidth = table.getWidth();
|
||||||
int rowHeight = table.getRowHeight();
|
int rowHeight = table.getRowHeight();
|
||||||
|
|
||||||
|
g.setColor( alternateColor );
|
||||||
|
|
||||||
|
int x = viewport.getComponentOrientation().isLeftToRight() ? 0 : viewportWidth - tableWidth;
|
||||||
for( int y = tableHeight, row = rowCount; y < viewportHeight; y += rowHeight, row++ ) {
|
for( int y = tableHeight, row = rowCount; y < viewportHeight; y += rowHeight, row++ ) {
|
||||||
if( row % 2 != 0 )
|
if( row % 2 != 0 )
|
||||||
g.fillRect( 0, y, tableWidth, rowHeight );
|
paintAlternateRowBackground( g, -1, -1, x, y, tableWidth, rowHeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add listener on demand
|
||||||
|
if( outsideAlternateRowsListener == null && table.getAutoResizeMode() == JTable.AUTO_RESIZE_OFF ) {
|
||||||
|
outsideAlternateRowsListener = new FlatOutsideAlternateRowsListener();
|
||||||
|
table.addComponentListener( outsideAlternateRowsListener );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints (rounded) alternate row background.
|
||||||
|
* Supports {@link #selectionArc} and {@link #selectionInsets}.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method is only invoked if either selection arc
|
||||||
|
* is greater than zero or if selection insets are not empty.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
protected void paintAlternateRowBackground( Graphics g, int row, int column, int x, int y, int width, int height ) {
|
||||||
|
Insets insets = (selectionInsets != null) ? (Insets) selectionInsets.clone() : null;
|
||||||
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
|
if( column >= 0 ) {
|
||||||
|
// selection insets
|
||||||
|
|
||||||
|
// selection arc
|
||||||
|
if( column > 0 ) {
|
||||||
|
if( insets != null )
|
||||||
|
insets.left = 0;
|
||||||
|
|
||||||
|
if( table.getComponentOrientation().isLeftToRight() )
|
||||||
|
arcTopLeft = arcBottomLeft = 0;
|
||||||
|
else
|
||||||
|
arcTopRight = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
if( column < table.getColumnCount() - 1 ) {
|
||||||
|
if( insets != null )
|
||||||
|
insets.right = 0;
|
||||||
|
|
||||||
|
if( table.getComponentOrientation().isLeftToRight() )
|
||||||
|
arcTopRight = arcBottomRight = 0;
|
||||||
|
else
|
||||||
|
arcTopLeft = arcBottomLeft = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||||
|
UIScale.scale( insets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints (rounded) cell selection.
|
||||||
|
* Supports {@link #selectionArc} and {@link #selectionInsets}.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method is only invoked if either selection arc
|
||||||
|
* is greater than zero or if selection insets are not empty.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
protected void paintCellSelection( Graphics g, int row, int column, int x, int y, int width, int height ) {
|
||||||
|
boolean rowSelAllowed = table.getRowSelectionAllowed();
|
||||||
|
boolean colSelAllowed = table.getColumnSelectionAllowed();
|
||||||
|
boolean rowSelOnly = rowSelAllowed && !colSelAllowed;
|
||||||
|
boolean colSelOnly = colSelAllowed && !rowSelAllowed;
|
||||||
|
boolean cellOnlySel = rowSelAllowed && colSelAllowed;
|
||||||
|
|
||||||
|
// get selection state of surrounding cells
|
||||||
|
boolean leftSelected = (column > 0 && (rowSelOnly || table.isCellSelected( row, column - 1 )));
|
||||||
|
boolean topSelected = (row > 0 && (colSelOnly || table.isCellSelected( row - 1, column )));
|
||||||
|
boolean rightSelected = (column < table.getColumnCount() - 1 && (rowSelOnly || table.isCellSelected( row, column + 1 )));
|
||||||
|
boolean bottomSelected = (row < table.getRowCount() - 1 && (colSelOnly || table.isCellSelected( row + 1, column )));
|
||||||
|
if( !table.getComponentOrientation().isLeftToRight() ) {
|
||||||
|
boolean temp = leftSelected;
|
||||||
|
leftSelected = rightSelected;
|
||||||
|
rightSelected = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// selection insets
|
||||||
|
// (insets are applied to whole row if row-only selection is used,
|
||||||
|
// or to whole column if column-only selection is used,
|
||||||
|
// or to cell if cell selection is used)
|
||||||
|
Insets insets = (selectionInsets != null) ? (Insets) selectionInsets.clone() : null;
|
||||||
|
if( insets != null ) {
|
||||||
|
if( rowSelOnly && leftSelected )
|
||||||
|
insets.left = 0;
|
||||||
|
if( rowSelOnly && rightSelected )
|
||||||
|
insets.right = 0;
|
||||||
|
if( colSelOnly && topSelected )
|
||||||
|
insets.top = 0;
|
||||||
|
if( colSelOnly && bottomSelected )
|
||||||
|
insets.bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// selection arc
|
||||||
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
|
if( selectionArc > 0 ) {
|
||||||
|
// note that intercellSpacing is not considered as a gap because
|
||||||
|
// grid lines are usually painted to intercell space
|
||||||
|
boolean hasRowGap = (rowSelOnly || cellOnlySel) && insets != null && (insets.top != 0 || insets.bottom != 0);
|
||||||
|
boolean hasColGap = (colSelOnly || cellOnlySel) && insets != null && (insets.left != 0 || insets.right != 0);
|
||||||
|
|
||||||
|
if( leftSelected && !hasColGap )
|
||||||
|
arcTopLeft = arcBottomLeft = 0;
|
||||||
|
if( rightSelected && !hasColGap )
|
||||||
|
arcTopRight = arcBottomRight = 0;
|
||||||
|
if( topSelected && !hasRowGap )
|
||||||
|
arcTopLeft = arcTopRight = 0;
|
||||||
|
if( bottomSelected && !hasRowGap )
|
||||||
|
arcBottomLeft = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||||
|
UIScale.scale( insets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints a cell selection at the given coordinates.
|
||||||
|
* The selection color must be set on the graphics context.
|
||||||
|
* <p>
|
||||||
|
* This method is intended for use in custom cell renderers to support
|
||||||
|
* {@link #selectionArc} and {@link #selectionInsets}.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void paintCellSelection( JTable table, Graphics g, int row, int column, int x, int y, int width, int height ) {
|
||||||
|
if( !(table.getUI() instanceof FlatTableUI) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
FlatTableUI ui = (FlatTableUI) table.getUI();
|
||||||
|
ui.paintCellSelection( g, row, column, x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installRepaintRoundedSelectionListeners() {
|
||||||
|
if( rowSelectionListener == null ) {
|
||||||
|
rowSelectionListener = this::repaintRoundedRowSelection;
|
||||||
|
table.getSelectionModel().addListSelectionListener( rowSelectionListener );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( columnSelectionListener == null ) {
|
||||||
|
columnSelectionListener = new TableColumnModelListener() {
|
||||||
|
@Override
|
||||||
|
public void columnSelectionChanged( ListSelectionEvent e ) {
|
||||||
|
repaintRoundedColumnSelection( e );
|
||||||
|
}
|
||||||
|
@Override public void columnRemoved( TableColumnModelEvent e ) {}
|
||||||
|
@Override public void columnMoved( TableColumnModelEvent e ) {}
|
||||||
|
@Override public void columnMarginChanged( ChangeEvent e ) {}
|
||||||
|
@Override public void columnAdded( TableColumnModelEvent e ) {}
|
||||||
|
};
|
||||||
|
table.getColumnModel().addColumnModelListener( columnSelectionListener );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintRoundedRowSelection( ListSelectionEvent e ) {
|
||||||
|
if( selectionArc <= 0 || !table.getRowSelectionAllowed() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int rowCount = table.getRowCount();
|
||||||
|
int columnCount = table.getColumnCount();
|
||||||
|
if( rowCount <= 0 || columnCount <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// repaint including rows before and after changed selection
|
||||||
|
int firstRow = Math.max( 0, Math.min( e.getFirstIndex() - 1, rowCount - 1 ) );
|
||||||
|
int lastRow = Math.max( 0, Math.min( e.getLastIndex() + 1, rowCount - 1 ) );
|
||||||
|
Rectangle firstRect = table.getCellRect( firstRow, 0, false );
|
||||||
|
Rectangle lastRect = table.getCellRect( lastRow, columnCount - 1, false );
|
||||||
|
table.repaint( firstRect.union( lastRect ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintRoundedColumnSelection( ListSelectionEvent e ) {
|
||||||
|
if( selectionArc <= 0 || !table.getColumnSelectionAllowed() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int rowCount = table.getRowCount();
|
||||||
|
int columnCount = table.getColumnCount();
|
||||||
|
if( rowCount <= 0 || columnCount <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// limit to selected rows for cell selection
|
||||||
|
int firstRow = 0;
|
||||||
|
int lastRow = rowCount - 1;
|
||||||
|
if( table.getRowSelectionAllowed() ) {
|
||||||
|
firstRow = table.getSelectionModel().getMinSelectionIndex();
|
||||||
|
lastRow = table.getSelectionModel().getMaxSelectionIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
// repaint including columns before and after changed selection
|
||||||
|
int firstColumn = Math.max( 0, Math.min( e.getFirstIndex() - 1, columnCount - 1 ) );
|
||||||
|
int lastColumn = Math.max( 0, Math.min( e.getLastIndex() + 1, columnCount - 1 ) );
|
||||||
|
Rectangle firstRect = table.getCellRect( firstRow, firstColumn, false );
|
||||||
|
Rectangle lastRect = table.getCellRect( lastRow, lastColumn, false );
|
||||||
|
table.repaint( firstRect.union( lastRect ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class RoundedSelectionGraphics -------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because selection painting is done in the cell renderer, it would be
|
||||||
|
* necessary to require a FlatLaf specific renderer to implement rounded selection.
|
||||||
|
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||||
|
* already used in applications. Then either the rounded selection is not used,
|
||||||
|
* or the application has to be changed to extend a FlatLaf renderer.
|
||||||
|
* <p>
|
||||||
|
* To solve this, a graphics proxy is used that paints rounded selection
|
||||||
|
* if row/column/cell is selected and the renderer wants to fill the background.
|
||||||
|
*/
|
||||||
|
private class RoundedSelectionGraphics
|
||||||
|
extends Graphics2DProxy
|
||||||
|
{
|
||||||
|
private final Color alternateRowColor;
|
||||||
|
|
||||||
|
// used to avoid endless loop in case that paintCellSelection() invokes
|
||||||
|
// g.fillRect() with full bounds (selectionInsets is 0,0,0,0)
|
||||||
|
private boolean inPaintSelection;
|
||||||
|
|
||||||
|
RoundedSelectionGraphics( Graphics delegate, Color alternateRowColor ) {
|
||||||
|
super( (Graphics2D) delegate );
|
||||||
|
this.alternateRowColor = alternateRowColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create() {
|
||||||
|
return new RoundedSelectionGraphics( super.create(), alternateRowColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create( int x, int y, int width, int height ) {
|
||||||
|
return new RoundedSelectionGraphics( super.create( x, y, width, height ), alternateRowColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillRect( int x, int y, int width, int height ) {
|
||||||
|
if( fillCellSelection( x, y, width, height ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
super.fillRect( x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fill( Shape shape ) {
|
||||||
|
if( shape instanceof Rectangle2D ) {
|
||||||
|
Rectangle2D r = (Rectangle2D) shape;
|
||||||
|
double x = r.getX();
|
||||||
|
double y = r.getY();
|
||||||
|
double width = r.getWidth();
|
||||||
|
double height = r.getHeight();
|
||||||
|
if( x == (int) x && y == (int) y && width == (int) width && height == (int) height ) {
|
||||||
|
if( fillCellSelection( (int) x, (int) y, (int) width, (int) height ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.fill( shape );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean fillCellSelection( int x, int y, int width, int height ) {
|
||||||
|
if( inPaintSelection )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Color color;
|
||||||
|
Component rendererComponent;
|
||||||
|
if( x == 0 && y == 0 &&
|
||||||
|
((color = getColor()) == table.getSelectionBackground() ||
|
||||||
|
(alternateRowColor != null && color == alternateRowColor)) &&
|
||||||
|
(rendererComponent = findActiveRendererComponent()) != null &&
|
||||||
|
width == rendererComponent.getWidth() &&
|
||||||
|
height == rendererComponent.getHeight() )
|
||||||
|
{
|
||||||
|
Point location = rendererComponent.getLocation();
|
||||||
|
int row = table.rowAtPoint( location );
|
||||||
|
int column = table.columnAtPoint( location );
|
||||||
|
if( row >= 0 && column >= 0 ) {
|
||||||
|
inPaintSelection = true;
|
||||||
|
if( color == table.getSelectionBackground() )
|
||||||
|
paintCellSelection( this, row, column, x, y, width, height );
|
||||||
|
else
|
||||||
|
paintAlternateRowBackground( this, row, column, x, y, width, height );
|
||||||
|
inPaintSelection = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A CellRendererPane may contain multiple components, if multiple renderers
|
||||||
|
* are used. Inactive renderer components have size {@code 0x0}.
|
||||||
|
*/
|
||||||
|
private Component findActiveRendererComponent() {
|
||||||
|
int count = rendererPane.getComponentCount();
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
Component c = rendererPane.getComponent( i );
|
||||||
|
if( c.getWidth() > 0 && c.getHeight() > 0 )
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class OutsideAlternateRowsListener ---------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used if table auto-resize-mode is off to repaint outside alternate rows
|
||||||
|
* when table width changed (column resized) or component orientation changed.
|
||||||
|
*/
|
||||||
|
private class FlatOutsideAlternateRowsListener
|
||||||
|
extends ComponentAdapter
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void componentHidden( ComponentEvent e ) {
|
||||||
|
Container viewport = SwingUtilities.getUnwrappedParent( table );
|
||||||
|
if( viewport instanceof JViewport )
|
||||||
|
HiDPIUtils.repaint( viewport );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentMoved( ComponentEvent e ) {
|
||||||
|
repaintAreaBelowTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentResized( ComponentEvent e ) {
|
||||||
|
repaintAreaBelowTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintAreaBelowTable() {
|
||||||
|
Container viewport = SwingUtilities.getUnwrappedParent( table );
|
||||||
|
if( viewport instanceof JViewport ) {
|
||||||
|
int viewportHeight = viewport.getHeight();
|
||||||
|
int tableHeight = table.getHeight();
|
||||||
|
if( tableHeight < viewportHeight )
|
||||||
|
HiDPIUtils.repaint( viewport, 0, tableHeight, viewport.getWidth(), viewportHeight - tableHeight );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -583,12 +990,14 @@ public class FlatTableUI
|
|||||||
|
|
||||||
FlatBooleanRenderer() {
|
FlatBooleanRenderer() {
|
||||||
setHorizontalAlignment( SwingConstants.CENTER );
|
setHorizontalAlignment( SwingConstants.CENTER );
|
||||||
setIcon( new FlatCheckBoxIcon() {
|
Icon icon = new FlatCheckBoxIcon() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSelected( Component c ) {
|
protected boolean isSelected( Component c ) {
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
} );
|
};
|
||||||
|
setIcon( icon );
|
||||||
|
setDisabledIcon( icon );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -174,8 +174,6 @@ public class FlatTextFieldUI
|
|||||||
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
||||||
|
|
||||||
LookAndFeel.installProperty( getComponent(), "opaque", false );
|
LookAndFeel.installProperty( getComponent(), "opaque", false );
|
||||||
|
|
||||||
MigLayoutVisualPadding.install( getComponent() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -193,8 +191,6 @@ public class FlatTextFieldUI
|
|||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
borderShared = null;
|
borderShared = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( getComponent() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -204,6 +200,8 @@ public class FlatTextFieldUI
|
|||||||
// necessary to update focus border and background
|
// necessary to update focus border and background
|
||||||
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
|
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
|
||||||
getComponent().addFocusListener( focusListener );
|
getComponent().addFocusListener( focusListener );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.install( getComponent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -217,6 +215,8 @@ public class FlatTextFieldUI
|
|||||||
getComponent().getDocument().removeDocumentListener( documentListener );
|
getComponent().getDocument().removeDocumentListener( documentListener );
|
||||||
documentListener = null;
|
documentListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.uninstall( getComponent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -239,7 +239,7 @@ public class FlatTextFieldUI
|
|||||||
case COMPONENT_ROUND_RECT:
|
case COMPONENT_ROUND_RECT:
|
||||||
case OUTLINE:
|
case OUTLINE:
|
||||||
case TEXT_FIELD_PADDING:
|
case TEXT_FIELD_PADDING:
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINIMUM_WIDTH:
|
case MINIMUM_WIDTH:
|
||||||
@@ -250,38 +250,38 @@ public class FlatTextFieldUI
|
|||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEXT_FIELD_LEADING_ICON:
|
case TEXT_FIELD_LEADING_ICON:
|
||||||
leadingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
leadingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEXT_FIELD_TRAILING_ICON:
|
case TEXT_FIELD_TRAILING_ICON:
|
||||||
trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEXT_FIELD_LEADING_COMPONENT:
|
case TEXT_FIELD_LEADING_COMPONENT:
|
||||||
uninstallLeadingComponent();
|
uninstallLeadingComponent();
|
||||||
installLeadingComponent();
|
installLeadingComponent();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEXT_FIELD_TRAILING_COMPONENT:
|
case TEXT_FIELD_TRAILING_COMPONENT:
|
||||||
uninstallTrailingComponent();
|
uninstallTrailingComponent();
|
||||||
installTrailingComponent();
|
installTrailingComponent();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEXT_FIELD_SHOW_CLEAR_BUTTON:
|
case TEXT_FIELD_SHOW_CLEAR_BUTTON:
|
||||||
uninstallClearButton();
|
uninstallClearButton();
|
||||||
installClearButton();
|
installClearButton();
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "enabled":
|
case "enabled":
|
||||||
@@ -815,7 +815,7 @@ debug*/
|
|||||||
if( visible != clearButton.isVisible() ) {
|
if( visible != clearButton.isVisible() ) {
|
||||||
clearButton.setVisible( visible );
|
clearButton.setVisible( visible );
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
HiDPIUtils.repaint( c );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import java.awt.Image;
|
|||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.ComponentAdapter;
|
import java.awt.event.ComponentAdapter;
|
||||||
@@ -90,13 +89,16 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TitlePane.iconSize Dimension
|
* @uiDefault TitlePane.iconSize Dimension
|
||||||
* @uiDefault TitlePane.iconMargins Insets
|
* @uiDefault TitlePane.iconMargins Insets
|
||||||
* @uiDefault TitlePane.titleMargins Insets
|
* @uiDefault TitlePane.titleMargins Insets
|
||||||
* @uiDefault TitlePane.menuBarEmbedded boolean
|
|
||||||
* @uiDefault TitlePane.titleMinimumWidth int
|
* @uiDefault TitlePane.titleMinimumWidth int
|
||||||
* @uiDefault TitlePane.buttonMinimumWidth int
|
* @uiDefault TitlePane.buttonMinimumWidth int
|
||||||
* @uiDefault TitlePane.buttonMaximizedHeight int
|
* @uiDefault TitlePane.buttonMaximizedHeight int
|
||||||
|
* @uiDefault TitlePane.buttonsGap int
|
||||||
|
* @uiDefault TitlePane.buttonsMargins Insets
|
||||||
|
* @uiDefault TitlePane.buttonsFillVertically boolean
|
||||||
* @uiDefault TitlePane.centerTitle boolean
|
* @uiDefault TitlePane.centerTitle boolean
|
||||||
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
||||||
* @uiDefault TitlePane.showIconBesideTitle boolean
|
* @uiDefault TitlePane.showIconBesideTitle boolean
|
||||||
|
* @uiDefault TitlePane.menuBarEmbedded boolean
|
||||||
* @uiDefault TitlePane.menuBarTitleGap int
|
* @uiDefault TitlePane.menuBarTitleGap int
|
||||||
* @uiDefault TitlePane.menuBarTitleMinimumGap int
|
* @uiDefault TitlePane.menuBarTitleMinimumGap int
|
||||||
* @uiDefault TitlePane.closeIcon Icon
|
* @uiDefault TitlePane.closeIcon Icon
|
||||||
@@ -124,9 +126,14 @@ public class FlatTitlePane
|
|||||||
/** @since 2.5 */ protected final boolean showIconInDialogs;
|
/** @since 2.5 */ protected final boolean showIconInDialogs;
|
||||||
/** @since 2 */ protected final int noIconLeftGap;
|
/** @since 2 */ protected final int noIconLeftGap;
|
||||||
protected final Dimension iconSize;
|
protected final Dimension iconSize;
|
||||||
|
/** @since 3.6 */ protected final Insets iconMargins;
|
||||||
|
/** @since 3.6 */ protected final Insets titleMargins;
|
||||||
/** @since 2.4 */ protected final int titleMinimumWidth;
|
/** @since 2.4 */ protected final int titleMinimumWidth;
|
||||||
/** @since 2.4 */ protected final int buttonMinimumWidth;
|
/** @since 2.4 */ protected final int buttonMinimumWidth;
|
||||||
protected final int buttonMaximizedHeight;
|
protected final int buttonMaximizedHeight;
|
||||||
|
/** @since 3.6 */ protected final int buttonsGap;
|
||||||
|
/** @since 3.6 */ protected final Insets buttonsMargins;
|
||||||
|
/** @since 3.6 */ protected final boolean buttonsFillVertically;
|
||||||
protected final boolean centerTitle;
|
protected final boolean centerTitle;
|
||||||
protected final boolean centerTitleIfMenuBarEmbedded;
|
protected final boolean centerTitleIfMenuBarEmbedded;
|
||||||
/** @since 2.4 */ protected final boolean showIconBesideTitle;
|
/** @since 2.4 */ protected final boolean showIconBesideTitle;
|
||||||
@@ -146,6 +153,9 @@ public class FlatTitlePane
|
|||||||
protected JButton restoreButton;
|
protected JButton restoreButton;
|
||||||
protected JButton closeButton;
|
protected JButton closeButton;
|
||||||
|
|
||||||
|
private JComponent iconifyMaximizeGapComp;
|
||||||
|
private JComponent maximizeCloseGapComp;
|
||||||
|
|
||||||
protected Window window;
|
protected Window window;
|
||||||
|
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
@@ -180,9 +190,7 @@ public class FlatTitlePane
|
|||||||
public FlatTitlePane( JRootPane rootPane ) {
|
public FlatTitlePane( JRootPane rootPane ) {
|
||||||
this.rootPane = rootPane;
|
this.rootPane = rootPane;
|
||||||
|
|
||||||
Window w = SwingUtilities.getWindowAncestor( rootPane );
|
windowStyle = getWindowStyle( rootPane );
|
||||||
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
|
|
||||||
windowStyle = clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
|
|
||||||
|
|
||||||
titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle );
|
titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle );
|
||||||
activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle );
|
activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle );
|
||||||
@@ -197,9 +205,14 @@ public class FlatTitlePane
|
|||||||
showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true );
|
showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true );
|
||||||
noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 );
|
noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 );
|
||||||
iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle );
|
iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle );
|
||||||
|
iconMargins = FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle );
|
||||||
|
titleMargins = FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle );
|
||||||
titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 );
|
titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 );
|
||||||
buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 );
|
buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 );
|
||||||
buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 );
|
buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 );
|
||||||
|
buttonsGap = FlatUIUtils.getSubUIInt( "TitlePane.buttonsGap", windowStyle, 0 );
|
||||||
|
buttonsMargins = FlatUIUtils.getSubUIInsets( "TitlePane.buttonsMargins", windowStyle );
|
||||||
|
buttonsFillVertically = FlatUIUtils.getSubUIBoolean( "TitlePane.buttonsFillVertically", windowStyle, true );
|
||||||
centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false );
|
centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false );
|
||||||
centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true );
|
centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true );
|
||||||
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
|
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
|
||||||
@@ -222,13 +235,19 @@ public class FlatTitlePane
|
|||||||
windowTopBorderLayer = new JPanel();
|
windowTopBorderLayer = new JPanel();
|
||||||
windowTopBorderLayer.setVisible( false );
|
windowTopBorderLayer.setVisible( false );
|
||||||
windowTopBorderLayer.setOpaque( false );
|
windowTopBorderLayer.setOpaque( false );
|
||||||
windowTopBorderLayer.setBorder( FlatUIUtils.nonUIResource( FlatNativeWindowBorder.WindowTopBorder.getInstance() ) );
|
windowTopBorderLayer.setBorder( FlatUIUtils.nonUIResource( WindowTopBorder.getInstance() ) );
|
||||||
} else
|
} else
|
||||||
windowTopBorderLayer = null;
|
windowTopBorderLayer = null;
|
||||||
|
|
||||||
applyComponentOrientation( rootPane.getComponentOrientation() );
|
applyComponentOrientation( rootPane.getComponentOrientation() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String getWindowStyle( JRootPane rootPane ) {
|
||||||
|
Window w = SwingUtilities.getWindowAncestor( rootPane );
|
||||||
|
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
|
||||||
|
return clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
|
||||||
|
}
|
||||||
|
|
||||||
protected FlatTitlePaneBorder createTitlePaneBorder() {
|
protected FlatTitlePaneBorder createTitlePaneBorder() {
|
||||||
return new FlatTitlePaneBorder();
|
return new FlatTitlePaneBorder();
|
||||||
}
|
}
|
||||||
@@ -246,8 +265,8 @@ public class FlatTitlePane
|
|||||||
setUI( new FlatTitleLabelUI() );
|
setUI( new FlatTitleLabelUI() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
iconLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle ) ) );
|
iconLabel.setBorder( new FlatEmptyBorder( iconMargins ) );
|
||||||
titleLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle ) ) );
|
titleLabel.setBorder( new FlatEmptyBorder( titleMargins ) );
|
||||||
|
|
||||||
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
||||||
leftPanel.setOpaque( false );
|
leftPanel.setOpaque( false );
|
||||||
@@ -350,23 +369,33 @@ public class FlatTitlePane
|
|||||||
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
|
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
|
||||||
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
|
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
|
||||||
|
|
||||||
|
iconifyMaximizeGapComp = createButtonsGapComp();
|
||||||
|
maximizeCloseGapComp = createButtonsGapComp();
|
||||||
|
|
||||||
// initially hide buttons that are only supported in frames
|
// initially hide buttons that are only supported in frames
|
||||||
iconifyButton.setVisible( false );
|
iconifyButton.setVisible( false );
|
||||||
maximizeButton.setVisible( false );
|
maximizeButton.setVisible( false );
|
||||||
restoreButton.setVisible( false );
|
restoreButton.setVisible( false );
|
||||||
|
iconifyMaximizeGapComp.setVisible( false );
|
||||||
|
maximizeCloseGapComp.setVisible( false );
|
||||||
|
|
||||||
buttonPanel = new JPanel() {
|
buttonPanel = new JPanel() {
|
||||||
@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 + buttonsMargins.top + buttonsMargins.bottom ) ) );
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buttonPanel.setOpaque( false );
|
buttonPanel.setOpaque( false );
|
||||||
|
buttonPanel.setBorder( FlatUIUtils.nonUIResource( new FlatEmptyBorder( buttonsMargins ) ) );
|
||||||
buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) );
|
buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) );
|
||||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||||
@@ -375,8 +404,10 @@ public class FlatTitlePane
|
|||||||
// later in frameStateChanged(), which is invoked from addNotify()
|
// later in frameStateChanged(), which is invoked from addNotify()
|
||||||
|
|
||||||
buttonPanel.add( iconifyButton );
|
buttonPanel.add( iconifyButton );
|
||||||
|
buttonPanel.add( iconifyMaximizeGapComp );
|
||||||
buttonPanel.add( maximizeButton );
|
buttonPanel.add( maximizeButton );
|
||||||
buttonPanel.add( restoreButton );
|
buttonPanel.add( restoreButton );
|
||||||
|
buttonPanel.add( maximizeCloseGapComp );
|
||||||
}
|
}
|
||||||
buttonPanel.add( closeButton );
|
buttonPanel.add( closeButton );
|
||||||
|
|
||||||
@@ -393,7 +424,17 @@ public class FlatTitlePane
|
|||||||
@Override
|
@Override
|
||||||
public Dimension getMinimumSize() {
|
public Dimension getMinimumSize() {
|
||||||
// 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(
|
||||||
|
Math.min( UIScale.scale( buttonMinimumWidth ), super.getPreferredSize().width ),
|
||||||
|
super.getMinimumSize().height );
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
// allow the button to fill whole button area height
|
||||||
|
// see also BasicMenuUI.getMaximumSize()
|
||||||
|
return buttonsFillVertically
|
||||||
|
? new Dimension( super.getMaximumSize().width, Short.MAX_VALUE )
|
||||||
|
: super.getMaximumSize();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
button.setFocusable( false );
|
button.setFocusable( false );
|
||||||
@@ -404,6 +445,14 @@ public class FlatTitlePane
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JComponent createButtonsGapComp() {
|
||||||
|
JComponent gapComp = new JPanel();
|
||||||
|
gapComp.setOpaque( false );
|
||||||
|
gapComp.setMinimumSize( new Dimension( 0, 0 ) );
|
||||||
|
gapComp.setPreferredSize( new Dimension( UIScale.scale( buttonsGap ), 0 ) );
|
||||||
|
return gapComp;
|
||||||
|
}
|
||||||
|
|
||||||
protected void activeChanged( boolean active ) {
|
protected void activeChanged( boolean active ) {
|
||||||
Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null );
|
Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null );
|
||||||
Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null );
|
Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null );
|
||||||
@@ -425,6 +474,9 @@ public class FlatTitlePane
|
|||||||
closeButton.setForeground( foreground );
|
closeButton.setForeground( foreground );
|
||||||
|
|
||||||
// this is necessary because hover/pressed colors are derived from background color
|
// this is necessary because hover/pressed colors are derived from background color
|
||||||
|
// (since FlatWindowAbstractIcon now invokes FlatTitlePane.getBackground()
|
||||||
|
// to get base color, this is no longer necessary, but keep it for compatibility;
|
||||||
|
// e.g. for custom window icons)
|
||||||
iconifyButton.setBackground( background );
|
iconifyButton.setBackground( background );
|
||||||
maximizeButton.setBackground( background );
|
maximizeButton.setBackground( background );
|
||||||
restoreButton.setBackground( background );
|
restoreButton.setBackground( background );
|
||||||
@@ -484,6 +536,13 @@ public class FlatTitlePane
|
|||||||
maximizeButton.setVisible( false );
|
maximizeButton.setVisible( false );
|
||||||
restoreButton.setVisible( false );
|
restoreButton.setVisible( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean iconifyVisible = iconifyButton.isVisible();
|
||||||
|
boolean maximizeVisible = maximizeButton.isVisible();
|
||||||
|
boolean restoreVisible = restoreButton.isVisible();
|
||||||
|
boolean closeVisible = closeButton.isVisible();
|
||||||
|
iconifyMaximizeGapComp.setVisible( iconifyVisible && (maximizeVisible || restoreVisible || closeVisible) );
|
||||||
|
maximizeCloseGapComp.setVisible( closeVisible && (maximizeVisible || restoreVisible) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateIcon() {
|
protected void updateIcon() {
|
||||||
@@ -737,22 +796,17 @@ public class FlatTitlePane
|
|||||||
if( isFullWindowContent() )
|
if( isFullWindowContent() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
|
g.setColor( getBackground() );
|
||||||
g.setColor( (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
|
||||||
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
|
|
||||||
? FlatUIUtils.getParentBackground( this )
|
|
||||||
: getBackground() );
|
|
||||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void repaintWindowBorder() {
|
@Override
|
||||||
int width = rootPane.getWidth();
|
public Color getBackground() {
|
||||||
int height = rootPane.getHeight();
|
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
|
||||||
Insets insets = rootPane.getInsets();
|
return (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||||
rootPane.repaint( 0, 0, width, insets.top ); // top
|
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
|
||||||
rootPane.repaint( 0, 0, insets.left, height ); // left
|
? FlatUIUtils.getParentBackground( this )
|
||||||
rootPane.repaint( 0, height - insets.bottom, width, insets.bottom ); // bottom
|
: super.getBackground();
|
||||||
rootPane.repaint( width - insets.right, 0, insets.right, height ); // right
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -824,7 +878,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();
|
||||||
|
|
||||||
@@ -859,7 +914,7 @@ public class FlatTitlePane
|
|||||||
// screen insets are in physical size, except for Java 15+
|
// screen insets are in physical size, except for Java 15+
|
||||||
// (see https://bugs.openjdk.java.net/browse/JDK-8243925)
|
// (see https://bugs.openjdk.java.net/browse/JDK-8243925)
|
||||||
// and except for Java 8 on secondary screens where primary screen is scaled
|
// and except for Java 8 on secondary screens where primary screen is scaled
|
||||||
Insets screenInsets = window.getToolkit().getScreenInsets( gc );
|
Insets screenInsets = FlatUIUtils.getScreenInsets( gc );
|
||||||
|
|
||||||
// maximized bounds are required in physical size, except for Java 15+
|
// maximized bounds are required in physical size, except for Java 15+
|
||||||
// (see https://bugs.openjdk.java.net/browse/JDK-8231564 and
|
// (see https://bugs.openjdk.java.net/browse/JDK-8231564 and
|
||||||
@@ -1058,10 +1113,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 ) {
|
||||||
@@ -1089,9 +1145,10 @@ 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
|
||||||
|
|
||||||
|
// check enabled component that has mouse listeners
|
||||||
if( c.isEnabled() &&
|
if( c.isEnabled() &&
|
||||||
(c.getMouseListeners().length > 0 ||
|
(c.getMouseListeners().length > 0 ||
|
||||||
c.getMouseMotionListeners().length > 0) )
|
c.getMouseMotionListeners().length > 0) )
|
||||||
@@ -1107,8 +1164,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
|
||||||
@@ -1141,6 +1208,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;
|
||||||
@@ -1352,10 +1429,7 @@ public class FlatTitlePane
|
|||||||
activeChanged( true );
|
activeChanged( true );
|
||||||
updateNativeTitleBarHeightAndHitTestSpots();
|
updateNativeTitleBarHeightAndHitTestSpots();
|
||||||
|
|
||||||
if( isWindowTopBorderNeeded() )
|
repaintBorder();
|
||||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
|
||||||
|
|
||||||
repaintWindowBorder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1363,10 +1437,22 @@ public class FlatTitlePane
|
|||||||
activeChanged( false );
|
activeChanged( false );
|
||||||
updateNativeTitleBarHeightAndHitTestSpots();
|
updateNativeTitleBarHeightAndHitTestSpots();
|
||||||
|
|
||||||
if( isWindowTopBorderNeeded() )
|
repaintBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintBorder() {
|
||||||
|
// Windows 10 top border
|
||||||
|
if( windowTopBorderLayer != null && windowTopBorderLayer.isShowing())
|
||||||
|
WindowTopBorder.getInstance().repaintBorder( windowTopBorderLayer );
|
||||||
|
else if( isWindowTopBorderNeeded() && !isWindowMaximized() && !isFullWindowContent() )
|
||||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||||
|
|
||||||
repaintWindowBorder();
|
// Window border used for non-native window decorations
|
||||||
|
if( rootPane.getBorder() instanceof FlatRootPaneUI.FlatWindowBorder ) {
|
||||||
|
// not repainting four areas on the four sides because RepaintManager
|
||||||
|
// unions dirty regions, which also results in repaint of whole rootpane
|
||||||
|
rootPane.repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1386,22 +1472,9 @@ debug*/
|
|||||||
|
|
||||||
private Point dragOffset;
|
private Point dragOffset;
|
||||||
private boolean linuxNativeMove;
|
private boolean linuxNativeMove;
|
||||||
private long lastSingleClickWhen;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked( MouseEvent e ) {
|
public void mouseClicked( MouseEvent e ) {
|
||||||
// on Linux, when using native library, the mouse clicked event
|
|
||||||
// is usually not sent and maximize/restore is done in mouse pressed event
|
|
||||||
// this check is here for the case that a mouse clicked event comes through for some reason
|
|
||||||
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
|
||||||
// see comment in mousePressed()
|
|
||||||
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
|
||||||
lastSingleClickWhen = 0;
|
|
||||||
maximizeOrRestore();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) {
|
if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) {
|
||||||
if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) {
|
if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) {
|
||||||
// double-click on icon closes window
|
// double-click on icon closes window
|
||||||
@@ -1432,42 +1505,6 @@ debug*/
|
|||||||
|
|
||||||
dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window );
|
dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window );
|
||||||
linuxNativeMove = false;
|
linuxNativeMove = false;
|
||||||
|
|
||||||
// on Linux, move or maximize/restore window
|
|
||||||
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
|
||||||
// The fired Java mouse events, when doing a double-click and the first click
|
|
||||||
// sends a _NET_WM_MOVERESIZE message, are different for various Linux distributions:
|
|
||||||
// CentOS 7 (GNOME 3.28.2, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
|
|
||||||
// Ubuntu 20.04 (GNOME 3.36.1, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
|
|
||||||
// Ubuntu 22.04 (GNOME 42.2, Wayland): PRESSED(clickCount=1) RELEASED(clickCount=1) CLICKED(clickCount=1)
|
|
||||||
// Kubuntu 22.04 (KDE 5.24.4, X11): PRESSED(clickCount=1) PRESSED(clickCount=1) RELEASED(clickCount=1)
|
|
||||||
|
|
||||||
// double-click is not always recognized in Java when using _NET_WM_MOVERESIZE message
|
|
||||||
int clickCount = e.getClickCount();
|
|
||||||
if( clickCount == 1 && lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() )
|
|
||||||
clickCount = 2;
|
|
||||||
|
|
||||||
switch( clickCount ) {
|
|
||||||
case 1:
|
|
||||||
// move window via _NET_WM_MOVERESIZE message
|
|
||||||
e.consume();
|
|
||||||
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
|
||||||
lastSingleClickWhen = e.getWhen();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// maximize/restore on double-click
|
|
||||||
// also done here because no mouse clicked event is sent when using _NET_WM_MOVERESIZE message
|
|
||||||
lastSingleClickWhen = 0;
|
|
||||||
maximizeOrRestore();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMultiClickInterval() {
|
|
||||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "awt.multiClickInterval" );
|
|
||||||
return (value instanceof Integer) ? (Integer) value : 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void mouseReleased( MouseEvent e ) {}
|
@Override public void mouseReleased( MouseEvent e ) {}
|
||||||
@@ -1490,6 +1527,13 @@ debug*/
|
|||||||
if( hasNativeCustomDecoration() )
|
if( hasNativeCustomDecoration() )
|
||||||
return; // do nothing if having native window border
|
return; // do nothing if having native window border
|
||||||
|
|
||||||
|
// on Linux, move window using window manager
|
||||||
|
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||||
|
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
||||||
|
if( linuxNativeMove )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// restore window if it is maximized
|
// restore window if it is maximized
|
||||||
if( window instanceof Frame ) {
|
if( window instanceof Frame ) {
|
||||||
Frame frame = (Frame) window;
|
Frame frame = (Frame) window;
|
||||||
@@ -1559,6 +1603,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
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import javax.swing.*;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,14 +160,14 @@ public class FlatToggleButtonUI
|
|||||||
b.revalidate();
|
b.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAB_BUTTON_UNDERLINE_PLACEMENT:
|
case TAB_BUTTON_UNDERLINE_PLACEMENT:
|
||||||
case TAB_BUTTON_UNDERLINE_HEIGHT:
|
case TAB_BUTTON_UNDERLINE_HEIGHT:
|
||||||
case TAB_BUTTON_UNDERLINE_COLOR:
|
case TAB_BUTTON_UNDERLINE_COLOR:
|
||||||
case TAB_BUTTON_SELECTED_BACKGROUND:
|
case TAB_BUTTON_SELECTED_BACKGROUND:
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,7 +132,7 @@ public class FlatToolBarSeparatorUI
|
|||||||
} else
|
} else
|
||||||
installStyle( s );
|
installStyle( s );
|
||||||
s.revalidate();
|
s.revalidate();
|
||||||
s.repaint();
|
HiDPIUtils.repaint( s );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicToolBarUI;
|
|||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -443,7 +444,7 @@ public class FlatToolBarUI
|
|||||||
|
|
||||||
// repaint button group
|
// repaint button group
|
||||||
if( gr != null )
|
if( gr != null )
|
||||||
toolBar.repaint( gr );
|
HiDPIUtils.repaint(toolBar, gr );
|
||||||
}
|
}
|
||||||
|
|
||||||
private ButtonGroup getButtonGroup( AbstractButton b ) {
|
private ButtonGroup getButtonGroup( AbstractButton b ) {
|
||||||
@@ -530,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 )
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class FlatToolTipUI
|
|||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
// update HTML renderer if necessary
|
// update HTML renderer if necessary
|
||||||
FlatLabelUI.updateHTMLRenderer( c, ((JToolTip)c).getTipText(), false );
|
FlatHTML.updateRendererCSSFontBaseSize( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,11 +81,7 @@ public class FlatToolTipUI
|
|||||||
/** @since 2.0.1 */
|
/** @since 2.0.1 */
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange( PropertyChangeEvent e ) {
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
String name = e.getPropertyName();
|
FlatHTML.propertyChange( e );
|
||||||
if( name == "tiptext" || name == "font" || name == "foreground" ) {
|
|
||||||
JToolTip toolTip = (JToolTip) e.getSource();
|
|
||||||
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import javax.swing.tree.DefaultTreeCellRenderer;
|
|||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -101,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
|
||||||
*
|
*
|
||||||
@@ -140,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;
|
||||||
|
|
||||||
@@ -191,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" );
|
||||||
|
|
||||||
@@ -226,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;
|
||||||
@@ -309,8 +317,9 @@ 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:
|
||||||
tree.repaint();
|
HiDPIUtils.repaint( tree );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "dropLocation":
|
case "dropLocation":
|
||||||
@@ -325,7 +334,7 @@ public class FlatTreeUI
|
|||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
tree.revalidate();
|
tree.revalidate();
|
||||||
tree.repaint();
|
HiDPIUtils.repaint( tree );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "enabled":
|
case "enabled":
|
||||||
@@ -353,7 +362,7 @@ public class FlatTreeUI
|
|||||||
|
|
||||||
Rectangle r = tree.getPathBounds( loc.getPath() );
|
Rectangle r = tree.getPathBounds( loc.getPath() );
|
||||||
if( r != null )
|
if( r != null )
|
||||||
tree.repaint( 0, r.y, tree.getWidth(), r.height );
|
HiDPIUtils.repaint( tree, 0, r.y, tree.getWidth(), r.height );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -370,14 +379,14 @@ public class FlatTreeUI
|
|||||||
{
|
{
|
||||||
if( changedPaths.length > 4 ) {
|
if( changedPaths.length > 4 ) {
|
||||||
// same is done in BasicTreeUI.Handler.valueChanged()
|
// same is done in BasicTreeUI.Handler.valueChanged()
|
||||||
tree.repaint();
|
HiDPIUtils.repaint( tree );
|
||||||
} else {
|
} else {
|
||||||
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||||
|
|
||||||
for( TreePath path : changedPaths ) {
|
for( TreePath path : changedPaths ) {
|
||||||
Rectangle r = getPathBounds( tree, path );
|
Rectangle r = getPathBounds( tree, path );
|
||||||
if( r != null )
|
if( r != null )
|
||||||
tree.repaint( r.x, r.y - arc, r.width, r.height + (arc * 2) );
|
HiDPIUtils.repaint( tree, r.x, r.y - arc, r.width, r.height + (arc * 2) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,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
|
||||||
@@ -794,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 );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.GraphicsDevice;
|
import java.awt.GraphicsDevice;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.KeyboardFocusManager;
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
@@ -34,6 +35,7 @@ import java.awt.RenderingHints;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.Stroke;
|
import java.awt.Stroke;
|
||||||
import java.awt.SystemColor;
|
import java.awt.SystemColor;
|
||||||
|
import java.awt.Toolkit;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
@@ -124,6 +126,25 @@ public class FlatUIUtils
|
|||||||
dest.right = src.right;
|
dest.right = src.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.5 */
|
||||||
|
public static boolean isInsetsEmpty( Insets insets ) {
|
||||||
|
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 );
|
||||||
@@ -395,6 +416,17 @@ public class FlatUIUtils
|
|||||||
return (fullScreenWindow != null && fullScreenWindow == SwingUtilities.windowForComponent( c ));
|
return (fullScreenWindow != null && fullScreenWindow == SwingUtilities.windowForComponent( c ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.6.1 */
|
||||||
|
public static Insets getScreenInsets( GraphicsConfiguration gc ) {
|
||||||
|
// on Linux, getScreenInsets() may report wrong values in multi-screen setups
|
||||||
|
// see https://github.com/apache/netbeans/issues/8532#issuecomment-2909687016
|
||||||
|
if( SystemInfo.isLinux &&
|
||||||
|
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length > 1 )
|
||||||
|
return new Insets( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
return Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
||||||
|
}
|
||||||
|
|
||||||
public static Boolean isRoundRect( Component c ) {
|
public static Boolean isRoundRect( Component c ) {
|
||||||
return (c instanceof JComponent)
|
return (c instanceof JComponent)
|
||||||
? FlatClientProperties.clientPropertyBooleanStrict(
|
? FlatClientProperties.clientPropertyBooleanStrict(
|
||||||
@@ -601,28 +633,55 @@ public class FlatUIUtils
|
|||||||
public static void paintOutlinedComponent( Graphics2D g, int x, int y, int width, int height,
|
public static void paintOutlinedComponent( Graphics2D g, int x, int y, int width, int height,
|
||||||
float focusWidth, float focusWidthFraction, float focusInnerWidth, float borderWidth, float arc,
|
float focusWidth, float focusWidthFraction, float focusInnerWidth, float borderWidth, float arc,
|
||||||
Paint focusColor, Paint borderColor, Paint background )
|
Paint focusColor, Paint borderColor, Paint background )
|
||||||
|
{
|
||||||
|
paintOutlinedComponent( g, x, y, width, height, focusWidth, focusWidthFraction, focusInnerWidth,
|
||||||
|
borderWidth, arc, focusColor, borderColor, background, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void paintOutlinedComponent( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
float focusWidth, float focusWidthFraction, float focusInnerWidth, float borderWidth, float arc,
|
||||||
|
Paint focusColor, Paint borderColor, Paint background, boolean scrollPane )
|
||||||
{
|
{
|
||||||
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
if( (int) systemScaleFactor != systemScaleFactor ) {
|
||||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
paintOutlinedComponentImpl( g2d, x2, y2, width2, height2,
|
paintOutlinedComponentImpl( g2d, x2, y2, width2, height2,
|
||||||
(float) (focusWidth * scaleFactor), focusWidthFraction, (float) (focusInnerWidth * scaleFactor),
|
(float) (focusWidth * scaleFactor), focusWidthFraction, (float) (focusInnerWidth * scaleFactor),
|
||||||
(float) (borderWidth * scaleFactor), (float) (arc * scaleFactor),
|
(float) (borderWidth * scaleFactor), (float) (arc * scaleFactor),
|
||||||
focusColor, borderColor, background );
|
focusColor, borderColor, background, scrollPane, scaleFactor );
|
||||||
} );
|
} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
paintOutlinedComponentImpl( g, x, y, width, height, focusWidth, focusWidthFraction, focusInnerWidth,
|
paintOutlinedComponentImpl( g, x, y, width, height, focusWidth, focusWidthFraction, focusInnerWidth,
|
||||||
borderWidth, arc, focusColor, borderColor, background );
|
borderWidth, arc, focusColor, borderColor, background, scrollPane, systemScaleFactor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "SelfAssignment" ) // Error Prone
|
||||||
private static void paintOutlinedComponentImpl( Graphics2D g, int x, int y, int width, int height,
|
private static void paintOutlinedComponentImpl( Graphics2D g, int x, int y, int width, int height,
|
||||||
float focusWidth, float focusWidthFraction, float focusInnerWidth, float borderWidth, float arc,
|
float focusWidth, float focusWidthFraction, float focusInnerWidth, float borderWidth, float arc,
|
||||||
Paint focusColor, Paint borderColor, Paint background )
|
Paint focusColor, Paint borderColor, Paint background, boolean scrollPane, double scaleFactor )
|
||||||
{
|
{
|
||||||
|
// Special handling for scrollpane and fractional scale factors (e.g. 1.25 - 1.75),
|
||||||
|
// where Swing scales one "logical" pixel (border insets) to either one or two physical pixels.
|
||||||
|
// Antialiasing is used to paint the border, which usually needs two physical pixels
|
||||||
|
// at small scale factors. 1px for the solid border and another 1px for antialiasing.
|
||||||
|
// But scrollpane view is painted over the border, which results in a painted border
|
||||||
|
// that is 1px thick at some sides and 2px thick at other sides.
|
||||||
|
if( scrollPane && scaleFactor != (int) scaleFactor ) {
|
||||||
|
if( focusWidth > 0 ) {
|
||||||
|
// reduce outer border thickness (focusWidth) so that inner side of
|
||||||
|
// component border (focusWidth + borderWidth) is at a full pixel
|
||||||
|
int totalWidth = (int) (focusWidth + borderWidth);
|
||||||
|
focusWidth = totalWidth - borderWidth;
|
||||||
|
} else {// if( scaleFactor > 1 && scaleFactor < 2 ) {
|
||||||
|
// reduce component border thickness (borderWidth) to full pixels
|
||||||
|
borderWidth = (int) borderWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// outside bounds of the border and the background
|
// outside bounds of the border and the background
|
||||||
float x1 = x + focusWidth;
|
float x1 = x + focusWidth;
|
||||||
float y1 = y + focusWidth;
|
float y1 = y + focusWidth;
|
||||||
@@ -780,7 +839,7 @@ public class FlatUIUtils
|
|||||||
|
|
||||||
if( arcTopLeft > 0 || arcTopRight > 0 || arcBottomLeft > 0 || arcBottomRight > 0 ) {
|
if( arcTopLeft > 0 || arcTopRight > 0 || arcBottomLeft > 0 || arcBottomRight > 0 ) {
|
||||||
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
if( systemScaleFactor != (int) systemScaleFactor ) {
|
||||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
@@ -1315,13 +1374,13 @@ debug*/
|
|||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
|
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
|
||||||
repaintComponent.repaint();
|
HiDPIUtils.repaint( repaintComponent );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
|
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
|
||||||
repaintComponent.repaint();
|
HiDPIUtils.repaint( repaintComponent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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, MouseEvent e ) {}
|
||||||
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 = FlatUIUtils.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,37 @@ public abstract class FlatWindowResizer
|
|||||||
public void windowStateChanged( WindowEvent e ) {
|
public void windowStateChanged( WindowEvent e ) {
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void beginResizing( int resizeDir, MouseEvent e ) {
|
||||||
|
// on Linux, resize window using window manager
|
||||||
|
if( SystemInfo.isLinux && window != null && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||||
|
int direction = -1;
|
||||||
|
switch( resizeDir ) {
|
||||||
|
case N_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOP; break;
|
||||||
|
case S_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOM; break;
|
||||||
|
case W_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_LEFT; break;
|
||||||
|
case E_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_RIGHT; break;
|
||||||
|
case NW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPLEFT; break;
|
||||||
|
case NE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPRIGHT; break;
|
||||||
|
case SW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMLEFT; break;
|
||||||
|
case SE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMRIGHT; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( direction >= 0 && FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, direction ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 +480,18 @@ public abstract class FlatWindowResizer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beginResizing( int direction ) {
|
protected void beginResizing( int resizeDir, MouseEvent e ) {
|
||||||
|
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 +599,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, e );
|
||||||
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
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Dialog;
|
|||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
|
import java.awt.Insets;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
@@ -39,6 +40,7 @@ import javax.swing.event.ChangeListener;
|
|||||||
import javax.swing.event.EventListenerList;
|
import javax.swing.event.EventListenerList;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Interesting resources:
|
// Interesting resources:
|
||||||
@@ -282,6 +284,8 @@ class FlatWindowsNativeWindowBorder
|
|||||||
HTMINBUTTON = 8,
|
HTMINBUTTON = 8,
|
||||||
HTMAXBUTTON = 9,
|
HTMAXBUTTON = 9,
|
||||||
HTTOP = 12,
|
HTTOP = 12,
|
||||||
|
HTTOPLEFT = 13,
|
||||||
|
HTTOPRIGHT = 14,
|
||||||
HTCLOSE = 20;
|
HTCLOSE = 20;
|
||||||
|
|
||||||
private Window window;
|
private Window window;
|
||||||
@@ -341,6 +345,31 @@ class FlatWindowsNativeWindowBorder
|
|||||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||||
Point pt = scaleDown( x, y );
|
Point pt = scaleDown( x, y );
|
||||||
|
|
||||||
|
// limit top resize border to 4px, which seems to be standard for modern WinUI apps
|
||||||
|
if( isOnResizeBorder && pt.y > UIScale.scale( 4 ) )
|
||||||
|
isOnResizeBorder = false;
|
||||||
|
|
||||||
|
if( isOnResizeBorder ) {
|
||||||
|
Insets insets = window.getInsets();
|
||||||
|
|
||||||
|
// return HTTOPLEFT if mouse is over top resize border on left side
|
||||||
|
// - hovering mouse shows top-left resize cursor
|
||||||
|
// - left-click-and-drag resizes window
|
||||||
|
if( pt.x <= insets.left + UIScale.scale( 12 ) )
|
||||||
|
return HTTOPLEFT;
|
||||||
|
|
||||||
|
// return HTTOPRIGHT if mouse is over top resize border on right side
|
||||||
|
// - hovering mouse shows top-right resize cursor
|
||||||
|
// - left-click-and-drag resizes window
|
||||||
|
if( pt.x >= window.getWidth() - insets.right - UIScale.scale( 12 ) )
|
||||||
|
return HTTOPRIGHT;
|
||||||
|
|
||||||
|
// return HTTOP if mouse is over top resize border
|
||||||
|
// - hovering mouse shows vertical resize cursor
|
||||||
|
// - left-click-and-drag vertically resizes window
|
||||||
|
return HTTOP;
|
||||||
|
}
|
||||||
|
|
||||||
// return HTSYSMENU if mouse is over application icon
|
// return HTSYSMENU if mouse is over application icon
|
||||||
// - left-click on HTSYSMENU area shows system menu
|
// - left-click on HTSYSMENU area shows system menu
|
||||||
// - double-left-click sends WM_CLOSE
|
// - double-left-click sends WM_CLOSE
|
||||||
@@ -364,12 +393,6 @@ class FlatWindowsNativeWindowBorder
|
|||||||
if( contains( closeButtonBounds, pt ) )
|
if( contains( closeButtonBounds, pt ) )
|
||||||
return HTCLOSE;
|
return HTCLOSE;
|
||||||
|
|
||||||
// return HTTOP if mouse is over top resize border
|
|
||||||
// - hovering mouse shows vertical resize cursor
|
|
||||||
// - left-click and drag vertically resizes window
|
|
||||||
if( isOnResizeBorder )
|
|
||||||
return HTTOP;
|
|
||||||
|
|
||||||
boolean isOnTitleBar = (pt.y < titleBarHeight);
|
boolean isOnTitleBar = (pt.y < titleBarHeight);
|
||||||
if( isOnTitleBar ) {
|
if( isOnTitleBar ) {
|
||||||
// return HTCLIENT if mouse is over any Swing component in title bar
|
// return HTCLIENT if mouse is over any Swing component in title bar
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import java.util.function.BiPredicate;
|
|||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
class StackUtils
|
public class StackUtils
|
||||||
{
|
{
|
||||||
private static final StackUtils INSTANCE = new StackUtilsImpl();
|
private static final StackUtils INSTANCE = new StackUtilsImpl();
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,9 @@ public class ColorFunctions
|
|||||||
if( functions.length == 1 && functions[0] instanceof Mix ) {
|
if( functions.length == 1 && functions[0] instanceof Mix ) {
|
||||||
Mix mixFunction = (Mix) functions[0];
|
Mix mixFunction = (Mix) functions[0];
|
||||||
return mix( color, mixFunction.color2, mixFunction.weight / 100 );
|
return mix( color, mixFunction.color2, mixFunction.weight / 100 );
|
||||||
|
} else if( functions.length == 1 && functions[0] instanceof Mix2 ) {
|
||||||
|
Mix2 mixFunction = (Mix2) functions[0];
|
||||||
|
return mix( mixFunction.color1, color, mixFunction.weight / 100 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert RGB to HSL
|
// convert RGB to HSL
|
||||||
@@ -386,7 +389,11 @@ public class ColorFunctions
|
|||||||
//---- class Mix ----------------------------------------------------------
|
//---- class Mix ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mix two colors.
|
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}.
|
||||||
|
* First color is passed to {@link #apply(float[])}.
|
||||||
|
* Second color is {@link #color2}.
|
||||||
|
* <p>
|
||||||
|
* Use {@link Mix2} to tint or shade color.
|
||||||
*
|
*
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
@@ -420,4 +427,44 @@ public class ColorFunctions
|
|||||||
return String.format( "mix(#%08x,%.0f%%)", color2.getRGB(), weight );
|
return String.format( "mix(#%08x,%.0f%%)", color2.getRGB(), weight );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class Mix2 ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}.
|
||||||
|
* First color is {@link #color1}.
|
||||||
|
* Second color is passed to {@link #apply(float[])}.
|
||||||
|
*
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
public static class Mix2
|
||||||
|
implements ColorFunction
|
||||||
|
{
|
||||||
|
public final Color color1;
|
||||||
|
public final float weight;
|
||||||
|
|
||||||
|
public Mix2( Color color1, float weight ) {
|
||||||
|
this.color1 = color1;
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply( float[] hsla ) {
|
||||||
|
// convert from HSL to RGB because color mixing is done on RGB values
|
||||||
|
Color color2 = HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
|
||||||
|
|
||||||
|
// mix
|
||||||
|
Color color = mix( color1, color2, weight / 100 );
|
||||||
|
|
||||||
|
// convert RGB to HSL
|
||||||
|
float[] hsl = HSLColor.fromRGB( color );
|
||||||
|
System.arraycopy( hsl, 0, hsla, 0, hsl.length );
|
||||||
|
hsla[3] = (color.getAlpha() / 255f) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format( "mix2(#%08x,%.0f%%)", color1.getRGB(), weight );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,21 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.util;
|
package com.formdev.flatlaf.util;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.font.GlyphVector;
|
import java.awt.font.GlyphVector;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.text.AttributedCharacterIterator;
|
import java.text.AttributedCharacterIterator;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.RepaintManager;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.FlatSystemProperties;
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
|
import com.formdev.flatlaf.ui.StackUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -320,6 +326,258 @@ public class HiDPIUtils
|
|||||||
public void drawGlyphVector( GlyphVector g, float x, float y ) {
|
public void drawGlyphVector( GlyphVector g, float x, float y ) {
|
||||||
super.drawGlyphVector( g, x, y + yCorrection );
|
super.drawGlyphVector( g, x, y + yCorrection );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillRect( int x, int y, int width, int height ) {
|
||||||
|
// fix hard coded black color in HRuleView.paint() of '<hr noshade>'
|
||||||
|
if( super.getColor() == Color.black &&
|
||||||
|
StackUtils.wasInvokedFrom( "javax.swing.text.html.HRuleView", "paint", 4 ) )
|
||||||
|
{
|
||||||
|
super.setColor( FlatLaf.isLafDark() ? Color.lightGray : Color.darkGray );
|
||||||
|
super.fillRect( x, y, width, height );
|
||||||
|
super.setColor( Color.black );
|
||||||
|
} else
|
||||||
|
super.fillRect( x, y, width, height );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repaints the given component.
|
||||||
|
* <p>
|
||||||
|
* See {@link #repaint(Component, int, int, int, int)} for more details.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void repaint( Component c ) {
|
||||||
|
repaint( c, 0, 0, c.getWidth(), c.getHeight() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repaints the given component area.
|
||||||
|
* <p>
|
||||||
|
* See {@link #repaint(Component, int, int, int, int)} for more details.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void repaint( Component c, Rectangle r ) {
|
||||||
|
repaint( c, r.x, r.y, r.width, r.height );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repaints the given component area.
|
||||||
|
* <p>
|
||||||
|
* Invokes {@link Component#repaint(int, int, int, int)} on the given component,
|
||||||
|
* <p>
|
||||||
|
* Use this method, instead of {@code Component.repaint(...)},
|
||||||
|
* to fix a problem in Swing when using scale factors that end on .25 or .75
|
||||||
|
* (e.g. 1.25, 1.75, 2.25, etc) and repainting single components, which may not
|
||||||
|
* repaint right and/or bottom 1px edge of component.
|
||||||
|
* <p>
|
||||||
|
* The problem may occur under following conditions:
|
||||||
|
* <ul>
|
||||||
|
* <li>using Java 9 or later
|
||||||
|
* <li>system scale factor is 125%, 175%, 225%, ...
|
||||||
|
* (Windows only; Java on macOS and Linux does not support fractional scale factors)
|
||||||
|
* <li>repaint whole component or right/bottom area of component
|
||||||
|
* <li>component is opaque; or component is contained in a opaque container
|
||||||
|
* that has same right/bottom bounds as component
|
||||||
|
* <li>component has bounds that Java/Swing scales different when repainting components
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void repaint( Component c, int x, int y, int width, int height ) {
|
||||||
|
// repaint given component area
|
||||||
|
// Always invoke repaint() on given component, even if also invoked (below)
|
||||||
|
// on one of its ancestors, for the case that component overrides that method.
|
||||||
|
// Also RepaintManager "merges" the two repaints into one.
|
||||||
|
c.repaint( x, y, width, height );
|
||||||
|
|
||||||
|
if( RepaintManager.currentManager( c ) instanceof HiDPIRepaintManager )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if necessary, also repaint given area in first ancestor that is larger than component
|
||||||
|
// to avoid clipping issue (see needsSpecialRepaint())
|
||||||
|
if( needsSpecialRepaint( c, x, y, width, height ) ) {
|
||||||
|
int x2 = x + c.getX();
|
||||||
|
int y2 = y + c.getY();
|
||||||
|
for( Component p = c.getParent(); p != null; p = p.getParent() ) {
|
||||||
|
x2 += p.getX();
|
||||||
|
y2 += p.getY();
|
||||||
|
if( x2 + width < p.getWidth() && y2 + height < p.getHeight() ) {
|
||||||
|
p.repaint( x2, y2, width, height );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is a problem in Swing, when using scale factors that end on .25 or .75
|
||||||
|
* (e.g. 1.25, 1.75, 2.25, etc) and repainting single components, which may not
|
||||||
|
* repaint right and/or bottom 1px edge of component.
|
||||||
|
* <p>
|
||||||
|
* The component is first painted to an in-memory image,
|
||||||
|
* and then that image is copied to the screen.
|
||||||
|
* See {@code javax.swing.RepaintManager.PaintManager#paintDoubleBufferedFPScales()}.
|
||||||
|
* <p>
|
||||||
|
* There are two clipping rectangles involved when copying the image to the screen:
|
||||||
|
* {@code sun.java2d.SunGraphics2D#devClip} and
|
||||||
|
* {@code sun.java2d.SunGraphics2D#usrClip}.
|
||||||
|
* <p>
|
||||||
|
* {@code devClip} is the device clipping in physical pixels.
|
||||||
|
* It gets the bounds of the painting component, which is either the passed component,
|
||||||
|
* or if it is non-opaque, then the first opaque ancestor of the passed component.
|
||||||
|
* It is calculated in {@code sun.java2d.SunGraphics2D#constrain()} while
|
||||||
|
* getting a graphics context via {@link JComponent#getGraphics()}.
|
||||||
|
* <p>
|
||||||
|
* {@code usrClip} is the user clipping, which is set via {@link Graphics} clipping methods.
|
||||||
|
* This is done in {@code javax.swing.RepaintManager.PaintManager#paintDoubleBufferedFPScales()}.
|
||||||
|
* <p>
|
||||||
|
* The intersection of {@code devClip} and {@code usrClip}
|
||||||
|
* (computed in {@code sun.java2d.SunGraphics2D#validateCompClip()})
|
||||||
|
* is used to copy the image to the screen.
|
||||||
|
* <p>
|
||||||
|
* Unfortunately different scaling/rounding strategies are used to calculate
|
||||||
|
* the two clipping rectangles, which is the reason of the issue.
|
||||||
|
* <p>
|
||||||
|
* {@code devClip} (see {@code sun.java2d.SunGraphics2D#constrain()}):
|
||||||
|
* <pre>{@code
|
||||||
|
* int devX = (int) (x * scale);
|
||||||
|
* int devWidth = Math.round( width * scale )
|
||||||
|
* }</pre>
|
||||||
|
* {@code usrClip} (see {@code javax.swing.RepaintManager.PaintManager#paintDoubleBufferedFPScales()}):
|
||||||
|
* <pre>{@code
|
||||||
|
* int usrX = (int) Math.ceil( (x * scale) - 0.5 );
|
||||||
|
* int usrWidth = ((int) Math.ceil( ((x + width) * scale) - 0.5 )) - usrX;
|
||||||
|
* }</pre>
|
||||||
|
* X/Y coordinates are always rounded down for {@code devClip}, but rounded up for {@code usrClip}.
|
||||||
|
* Width/height calculation is also different.
|
||||||
|
*/
|
||||||
|
private static boolean needsSpecialRepaint( Component c, int x, int y, int width, int height ) {
|
||||||
|
// no special repaint necessary for Java 8 or for macOS and Linux
|
||||||
|
// (Java on those platforms does not support fractional scale factors)
|
||||||
|
if( !SystemInfo.isJava_9_orLater || !SystemInfo.isWindows )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check whether repaint area is empty or no component given
|
||||||
|
// (same checks as in javax.swing.RepaintManager.addDirtyRegion0())
|
||||||
|
if( width <= 0 || height <= 0 || c == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check whether component has zero size
|
||||||
|
// (same checks as in javax.swing.RepaintManager.addDirtyRegion0())
|
||||||
|
int compWidth = c.getWidth();
|
||||||
|
int compHeight = c.getHeight();
|
||||||
|
if( compWidth <= 0 || compHeight <= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check whether repaint area does span to right or bottom component edges
|
||||||
|
// (in this case, {@code devClip} is always larger than {@code usrClip})
|
||||||
|
if( x + width < compWidth && y + height < compHeight )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if component is not opaque, Swing uses the first opaque ancestor for painting
|
||||||
|
if( !c.isOpaque() ) {
|
||||||
|
int x2 = x;
|
||||||
|
int y2 = y;
|
||||||
|
for( Component p = c.getParent(); p != null; p = p.getParent() ) {
|
||||||
|
x2 += p.getX();
|
||||||
|
y2 += p.getY();
|
||||||
|
if( p.isOpaque() ) {
|
||||||
|
// check whether repaint area does span to right or bottom edges
|
||||||
|
// of the opaque ancestor component
|
||||||
|
// (in this case, {@code devClip} is always larger than {@code usrClip})
|
||||||
|
if( x2 + width < p.getWidth() && y2 + height < p.getHeight() )
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether Special repaint is necessary for current scale factor
|
||||||
|
// (doing this check late because it temporary allocates some memory)
|
||||||
|
double scaleFactor = UIScale.getSystemScaleFactor( c.getGraphicsConfiguration() );
|
||||||
|
double fraction = scaleFactor - (int) scaleFactor;
|
||||||
|
if( fraction == 0 || fraction == 0.5 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs a {@link HiDPIRepaintManager} on Windows when running in Java 9+,
|
||||||
|
* but only if default repaint manager is currently installed.
|
||||||
|
* <p>
|
||||||
|
* Invoke once on application startup.
|
||||||
|
* Compatible with all/other LaFs.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void installHiDPIRepaintManager() {
|
||||||
|
if( !SystemInfo.isJava_9_orLater || !SystemInfo.isWindows )
|
||||||
|
return;
|
||||||
|
|
||||||
|
RepaintManager manager = RepaintManager.currentManager( (Component) null );
|
||||||
|
if( manager.getClass() == RepaintManager.class )
|
||||||
|
RepaintManager.setCurrentManager( new HiDPIRepaintManager() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link #repaint(Component, int, int, int, int)},
|
||||||
|
* but invokes callback instead of invoking {@link Component#repaint(int, int, int, int)}.
|
||||||
|
* <p>
|
||||||
|
* For use in custom repaint managers.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void addDirtyRegion( JComponent c, int x, int y, int width, int height, DirtyRegionCallback callback ) {
|
||||||
|
if( needsSpecialRepaint( c, x, y, width, height ) ) {
|
||||||
|
int x2 = x + c.getX();
|
||||||
|
int y2 = y + c.getY();
|
||||||
|
for( Component p = c.getParent(); p != null; p = p.getParent() ) {
|
||||||
|
if( x2 + width < p.getWidth() && y2 + height < p.getHeight() && p instanceof JComponent ) {
|
||||||
|
callback.addDirtyRegion( (JComponent) p, x2, y2, width, height );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
x2 += p.getX();
|
||||||
|
y2 += p.getY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.addDirtyRegion( c, x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface DirtyRegionCallback --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For {@link HiDPIUtils#addDirtyRegion(JComponent, int, int, int, int, DirtyRegionCallback)}.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public interface DirtyRegionCallback {
|
||||||
|
void addDirtyRegion( JComponent c, int x, int y, int w, int h );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class HiDPIRepaintManager ------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repaint manager that fixes a problem in Swing when repainting components
|
||||||
|
* at some scale factors (e.g. 125%, 175%, etc) on Windows.
|
||||||
|
* <p>
|
||||||
|
* Use {@link HiDPIUtils#installHiDPIRepaintManager()} to install it.
|
||||||
|
* <p>
|
||||||
|
* See {@link HiDPIUtils#repaint(Component, int, int, int, int)} for details.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static class HiDPIRepaintManager
|
||||||
|
extends RepaintManager
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void addDirtyRegion( JComponent c, int x, int y, int w, int h ) {
|
||||||
|
HiDPIUtils.addDirtyRegion( c, x, y, w, h, super::addDirtyRegion );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public class SystemInfo
|
|||||||
public static final boolean isWindows;
|
public static final boolean isWindows;
|
||||||
public static final boolean isMacOS;
|
public static final boolean isMacOS;
|
||||||
public static final boolean isLinux;
|
public static final boolean isLinux;
|
||||||
|
/** @since 3.6 */ public static final boolean isUnknownOS;
|
||||||
|
|
||||||
// OS versions
|
// OS versions
|
||||||
public static final long osVersion;
|
public static final long osVersion;
|
||||||
@@ -59,6 +60,7 @@ public class SystemInfo
|
|||||||
public static final boolean isJetBrainsJVM_11_orLater;
|
public static final boolean isJetBrainsJVM_11_orLater;
|
||||||
|
|
||||||
// UI toolkits
|
// UI toolkits
|
||||||
|
/** @since 3.6 */ public static final boolean isGNOME;
|
||||||
public static final boolean isKDE;
|
public static final boolean isKDE;
|
||||||
|
|
||||||
// other
|
// other
|
||||||
@@ -75,6 +77,7 @@ public class SystemInfo
|
|||||||
isWindows = osName.startsWith( "windows" );
|
isWindows = osName.startsWith( "windows" );
|
||||||
isMacOS = osName.startsWith( "mac" );
|
isMacOS = osName.startsWith( "mac" );
|
||||||
isLinux = osName.startsWith( "linux" );
|
isLinux = osName.startsWith( "linux" );
|
||||||
|
isUnknownOS = !isWindows && !isMacOS && !isLinux;
|
||||||
|
|
||||||
// OS versions
|
// OS versions
|
||||||
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
||||||
@@ -104,7 +107,13 @@ public class SystemInfo
|
|||||||
isJetBrainsJVM_11_orLater = isJetBrainsJVM && isJava_11_orLater;
|
isJetBrainsJVM_11_orLater = isJetBrainsJVM && isJava_11_orLater;
|
||||||
|
|
||||||
// UI toolkits
|
// UI toolkits
|
||||||
isKDE = (isLinux && System.getenv( "KDE_FULL_SESSION" ) != null);
|
String desktop = isLinux ? System.getenv( "XDG_CURRENT_DESKTOP" ) : null;
|
||||||
|
isGNOME = (isLinux &&
|
||||||
|
(System.getenv( "GNOME_DESKTOP_SESSION_ID" ) != null ||
|
||||||
|
(desktop != null && desktop.contains( "GNOME" ))));
|
||||||
|
isKDE = (isLinux &&
|
||||||
|
(System.getenv( "KDE_FULL_SESSION" ) != null ||
|
||||||
|
(desktop != null && desktop.contains( "KDE" ))));
|
||||||
|
|
||||||
// other
|
// other
|
||||||
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
|
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ Component.arrowType = triangle
|
|||||||
#---- ProgressBar ----
|
#---- ProgressBar ----
|
||||||
|
|
||||||
ProgressBar.foreground = darken(@foreground,10%)
|
ProgressBar.foreground = darken(@foreground,10%)
|
||||||
ProgressBar.selectionForeground = @background
|
|
||||||
|
|
||||||
|
|
||||||
#---- RadioButton ----
|
#---- RadioButton ----
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
# general background and foreground (text color)
|
# general background and foreground (text color)
|
||||||
@background = #3c3f41
|
@background = #3c3f41
|
||||||
@foreground = #bbb
|
@foreground = #ddd
|
||||||
@disabledBackground = @background
|
@disabledBackground = @background
|
||||||
@disabledForeground = shade(@foreground,25%)
|
@disabledForeground = shade(@foreground,25%)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
# selection
|
# selection
|
||||||
@selectionBackground = @accentSelectionBackground
|
@selectionBackground = @accentSelectionBackground
|
||||||
@selectionForeground = contrast(@selectionBackground, @background, @foreground, 25%)
|
@selectionForeground = contrast(@selectionBackground, shade(@background), tint(@foreground), 25%)
|
||||||
@selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15)
|
@selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15)
|
||||||
@selectionInactiveForeground = @foreground
|
@selectionInactiveForeground = @foreground
|
||||||
|
|
||||||
@@ -187,6 +187,8 @@ Component.error.borderColor = desaturate($Component.error.focusedBorderColor,25%
|
|||||||
Component.error.focusedBorderColor = #8b3c3c
|
Component.error.focusedBorderColor = #8b3c3c
|
||||||
Component.warning.borderColor = darken(desaturate($Component.warning.focusedBorderColor,20%),10%)
|
Component.warning.borderColor = darken(desaturate($Component.warning.focusedBorderColor,20%),10%)
|
||||||
Component.warning.focusedBorderColor = #ac7920
|
Component.warning.focusedBorderColor = #ac7920
|
||||||
|
Component.success.borderColor = desaturate($Component.success.focusedBorderColor,25%)
|
||||||
|
Component.success.focusedBorderColor = #648b3c
|
||||||
Component.custom.borderColor = desaturate(#f00,50%,relative derived noAutoInverse)
|
Component.custom.borderColor = desaturate(#f00,50%,relative derived noAutoInverse)
|
||||||
|
|
||||||
|
|
||||||
@@ -262,7 +264,7 @@ PopupMenu.hoverScrollArrowBackground = lighten(@background,5%)
|
|||||||
ProgressBar.background = lighten(@background,8%)
|
ProgressBar.background = lighten(@background,8%)
|
||||||
ProgressBar.foreground = @accentSliderColor
|
ProgressBar.foreground = @accentSliderColor
|
||||||
ProgressBar.selectionBackground = @foreground
|
ProgressBar.selectionBackground = @foreground
|
||||||
ProgressBar.selectionForeground = contrast($ProgressBar.foreground, @background, @foreground, 25%)
|
ProgressBar.selectionForeground = contrast($ProgressBar.foreground, shade(@background), tint(@foreground), 25%)
|
||||||
|
|
||||||
|
|
||||||
#---- RootPane ----
|
#---- RootPane ----
|
||||||
@@ -274,7 +276,7 @@ RootPane.inactiveBorderColor = lighten(@background,5%,derived)
|
|||||||
#---- ScrollBar ----
|
#---- ScrollBar ----
|
||||||
|
|
||||||
ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
|
ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
|
||||||
ScrollBar.thumb = lighten($ScrollBar.track,10%,derived noAutoInverse)
|
ScrollBar.thumb = lighten($ScrollBar.track,15%,derived noAutoInverse)
|
||||||
ScrollBar.hoverTrackColor = lighten($ScrollBar.track,4%,derived noAutoInverse)
|
ScrollBar.hoverTrackColor = lighten($ScrollBar.track,4%,derived noAutoInverse)
|
||||||
ScrollBar.hoverThumbColor = lighten($ScrollBar.thumb,10%,derived noAutoInverse)
|
ScrollBar.hoverThumbColor = lighten($ScrollBar.thumb,10%,derived noAutoInverse)
|
||||||
ScrollBar.pressedThumbColor = lighten($ScrollBar.thumb,15%,derived noAutoInverse)
|
ScrollBar.pressedThumbColor = lighten($ScrollBar.thumb,15%,derived noAutoInverse)
|
||||||
@@ -284,7 +286,7 @@ ScrollBar.pressedButtonBackground = lighten(@background,10%,derived noAutoInvers
|
|||||||
|
|
||||||
#---- Separator ----
|
#---- Separator ----
|
||||||
|
|
||||||
Separator.foreground = tint(@background,10%)
|
Separator.foreground = tint(@background,15%)
|
||||||
|
|
||||||
|
|
||||||
#---- Slider ----
|
#---- Slider ----
|
||||||
@@ -341,8 +343,13 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
|||||||
#---- TitlePane ----
|
#---- TitlePane ----
|
||||||
|
|
||||||
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
||||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,15%,derived)
|
TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
||||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,10%,derived)
|
TitlePane.buttonPressedBackground = lighten($TitlePane.background,6%,derived)
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
[linux]TitlePane.buttonBackground = lighten($TitlePane.background,5%,derived)
|
||||||
|
[linux]TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
||||||
|
[linux]TitlePane.buttonPressedBackground = lighten($TitlePane.background,15%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ mini.font = -3
|
|||||||
#defaultFont = ...
|
#defaultFont = ...
|
||||||
|
|
||||||
# font weights
|
# font weights
|
||||||
|
# fallback for unknown platform
|
||||||
|
light.font = +0
|
||||||
|
semibold.font = +0
|
||||||
# Windows
|
# Windows
|
||||||
[win]light.font = "Segoe UI Light"
|
[win]light.font = "Segoe UI Light"
|
||||||
[win]semibold.font = "Segoe UI Semibold"
|
[win]semibold.font = "Segoe UI Semibold"
|
||||||
@@ -59,15 +62,12 @@ mini.font = -3
|
|||||||
# Linux
|
# Linux
|
||||||
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
|
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
|
||||||
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold"
|
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold"
|
||||||
# fallback for unknown platform
|
|
||||||
light.font = +0
|
|
||||||
semibold.font = +0
|
|
||||||
|
|
||||||
# monospaced
|
# monospaced
|
||||||
|
monospaced.font = Monospaced
|
||||||
[win]monospaced.font = Monospaced
|
[win]monospaced.font = Monospaced
|
||||||
[mac]monospaced.font = Menlo, Monospaced
|
[mac]monospaced.font = Menlo, Monospaced
|
||||||
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
|
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
|
||||||
monospaced.font = Monospaced
|
|
||||||
|
|
||||||
# styles
|
# styles
|
||||||
[style].h00 = font: $h00.font
|
[style].h00 = font: $h00.font
|
||||||
@@ -564,8 +564,8 @@ RadioButtonMenuItem.background = @menuBackground
|
|||||||
#---- RootPane ----
|
#---- RootPane ----
|
||||||
|
|
||||||
RootPane.border = com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder
|
RootPane.border = com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder
|
||||||
RootPane.borderDragThickness = 5
|
RootPane.borderDragThickness = 6
|
||||||
RootPane.cornerDragWidth = 16
|
RootPane.cornerDragWidth = 32
|
||||||
RootPane.honorFrameMinimumSizeOnResize = false
|
RootPane.honorFrameMinimumSizeOnResize = false
|
||||||
RootPane.honorDialogMinimumSizeOnResize = true
|
RootPane.honorDialogMinimumSizeOnResize = true
|
||||||
|
|
||||||
@@ -574,12 +574,12 @@ RootPane.honorDialogMinimumSizeOnResize = true
|
|||||||
|
|
||||||
ScrollBar.width = 10
|
ScrollBar.width = 10
|
||||||
ScrollBar.minimumButtonSize = 12,12
|
ScrollBar.minimumButtonSize = 12,12
|
||||||
ScrollBar.minimumThumbSize = 10,10
|
ScrollBar.minimumThumbSize = 18,18
|
||||||
ScrollBar.maximumThumbSize = 100000,100000
|
ScrollBar.maximumThumbSize = 100000,100000
|
||||||
ScrollBar.trackInsets = 0,0,0,0
|
ScrollBar.trackInsets = 0,0,0,0
|
||||||
ScrollBar.thumbInsets = 0,0,0,0
|
ScrollBar.thumbInsets = 2,2,2,2
|
||||||
ScrollBar.trackArc = 0
|
ScrollBar.trackArc = 0
|
||||||
ScrollBar.thumbArc = 0
|
ScrollBar.thumbArc = 999
|
||||||
ScrollBar.hoverThumbWithTrack = false
|
ScrollBar.hoverThumbWithTrack = false
|
||||||
ScrollBar.pressedThumbWithTrack = false
|
ScrollBar.pressedThumbWithTrack = false
|
||||||
ScrollBar.showButtons = false
|
ScrollBar.showButtons = false
|
||||||
@@ -588,15 +588,8 @@ ScrollBar.buttonArrowColor = @buttonArrowColor
|
|||||||
ScrollBar.buttonDisabledArrowColor = @buttonDisabledArrowColor
|
ScrollBar.buttonDisabledArrowColor = @buttonDisabledArrowColor
|
||||||
ScrollBar.allowsAbsolutePositioning = true
|
ScrollBar.allowsAbsolutePositioning = true
|
||||||
|
|
||||||
[mac]ScrollBar.minimumThumbSize = 18,18
|
|
||||||
[mac]ScrollBar.thumbInsets = 2,2,2,2
|
|
||||||
[mac]ScrollBar.thumbArc = 999
|
|
||||||
[mac]ScrollBar.hoverThumbWithTrack = true
|
[mac]ScrollBar.hoverThumbWithTrack = true
|
||||||
|
|
||||||
[linux]ScrollBar.minimumThumbSize = 18,18
|
|
||||||
[linux]ScrollBar.thumbInsets = 2,2,2,2
|
|
||||||
[linux]ScrollBar.thumbArc = 999
|
|
||||||
|
|
||||||
|
|
||||||
#---- ScrollPane ----
|
#---- ScrollPane ----
|
||||||
|
|
||||||
@@ -823,9 +816,14 @@ TitlePane.iconMargins = 3,8,3,8
|
|||||||
TitlePane.titleMargins = 3,0,3,0
|
TitlePane.titleMargins = 3,0,3,0
|
||||||
TitlePane.titleMinimumWidth = 60
|
TitlePane.titleMinimumWidth = 60
|
||||||
TitlePane.buttonSize = 44,30
|
TitlePane.buttonSize = 44,30
|
||||||
|
TitlePane.buttonInsets = 0,0,0,0
|
||||||
|
TitlePane.buttonArc = 0
|
||||||
TitlePane.buttonMinimumWidth = 30
|
TitlePane.buttonMinimumWidth = 30
|
||||||
TitlePane.buttonMaximizedHeight = 22
|
TitlePane.buttonMaximizedHeight = 22
|
||||||
TitlePane.buttonSymbolHeight = 10
|
TitlePane.buttonSymbolHeight = 10
|
||||||
|
TitlePane.buttonsGap = 0
|
||||||
|
TitlePane.buttonsMargins = 0,0,0,0
|
||||||
|
TitlePane.buttonsFillVertically = true
|
||||||
TitlePane.centerTitle = false
|
TitlePane.centerTitle = false
|
||||||
TitlePane.centerTitleIfMenuBarEmbedded = true
|
TitlePane.centerTitleIfMenuBarEmbedded = true
|
||||||
TitlePane.showIconBesideTitle = false
|
TitlePane.showIconBesideTitle = false
|
||||||
@@ -856,6 +854,27 @@ TitlePane.small.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon, s
|
|||||||
TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small
|
TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small
|
||||||
TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small
|
TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
[linux]TitlePane.buttonSize = 26,26
|
||||||
|
[linux]TitlePane.buttonInsets = 2,2,2,2
|
||||||
|
[linux]TitlePane.buttonArc = 999
|
||||||
|
[linux]TitlePane.buttonMaximizedHeight = -1
|
||||||
|
[linux]TitlePane.buttonSymbolHeight = 8
|
||||||
|
[linux]TitlePane.buttonsGap = 8
|
||||||
|
[linux]TitlePane.buttonsMargins = 4,4,4,4
|
||||||
|
[linux]TitlePane.buttonsFillVertically = false
|
||||||
|
[linux]TitlePane.small.buttonSize = 20,20
|
||||||
|
[linux]TitlePane.small.buttonInsets = 1,1,1,1
|
||||||
|
[linux]TitlePane.small.buttonSymbolHeight = 6
|
||||||
|
[linux]TitlePane.small.buttonsGap = 4
|
||||||
|
[linux]TitlePane.small.buttonsMargins = 2,2,2,2
|
||||||
|
[linux]TitlePane.closeBackground = $?TitlePane.buttonBackground
|
||||||
|
[linux]TitlePane.closeInactiveBackground = $?TitlePane.buttonInactiveBackground
|
||||||
|
[linux]TitlePane.closeHoverBackground = $?TitlePane.buttonHoverBackground
|
||||||
|
[linux]TitlePane.closePressedBackground = $?TitlePane.buttonPressedBackground
|
||||||
|
[linux]TitlePane.closeHoverForeground = $?TitlePane.foreground
|
||||||
|
[linux]TitlePane.closePressedForeground = $?TitlePane.foreground
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|
||||||
@@ -934,6 +953,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
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
@background = #f2f2f2
|
@background = #f2f2f2
|
||||||
@foreground = #000
|
@foreground = #000
|
||||||
@disabledBackground = @background
|
@disabledBackground = @background
|
||||||
@disabledForeground = tint(@foreground,55%)
|
@disabledForeground = tint(@foreground,50%)
|
||||||
|
|
||||||
# component background
|
# component background
|
||||||
@buttonBackground = lighten(@background,5%)
|
@buttonBackground = lighten(@background,5%)
|
||||||
@@ -194,6 +194,8 @@ Component.error.borderColor = lighten(desaturate($Component.error.focusedBorderC
|
|||||||
Component.error.focusedBorderColor = #e53e4d
|
Component.error.focusedBorderColor = #e53e4d
|
||||||
Component.warning.borderColor = lighten(saturate($Component.warning.focusedBorderColor,25%),20%)
|
Component.warning.borderColor = lighten(saturate($Component.warning.focusedBorderColor,25%),20%)
|
||||||
Component.warning.focusedBorderColor = #e2a53a
|
Component.warning.focusedBorderColor = #e2a53a
|
||||||
|
Component.success.borderColor = lighten(desaturate($Component.success.focusedBorderColor,20%),25%)
|
||||||
|
Component.success.focusedBorderColor = #14dc92
|
||||||
Component.custom.borderColor = lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse)
|
Component.custom.borderColor = lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse)
|
||||||
|
|
||||||
|
|
||||||
@@ -280,7 +282,7 @@ RootPane.inactiveBorderColor = darken(@background,30%,derived)
|
|||||||
#---- ScrollBar ----
|
#---- ScrollBar ----
|
||||||
|
|
||||||
ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
|
ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
|
||||||
ScrollBar.thumb = darken($ScrollBar.track,10%,derived noAutoInverse)
|
ScrollBar.thumb = darken($ScrollBar.track,15%,derived noAutoInverse)
|
||||||
ScrollBar.hoverTrackColor = darken($ScrollBar.track,3%,derived noAutoInverse)
|
ScrollBar.hoverTrackColor = darken($ScrollBar.track,3%,derived noAutoInverse)
|
||||||
ScrollBar.hoverThumbColor = darken($ScrollBar.thumb,10%,derived noAutoInverse)
|
ScrollBar.hoverThumbColor = darken($ScrollBar.thumb,10%,derived noAutoInverse)
|
||||||
ScrollBar.pressedThumbColor = darken($ScrollBar.thumb,20%,derived noAutoInverse)
|
ScrollBar.pressedThumbColor = darken($ScrollBar.thumb,20%,derived noAutoInverse)
|
||||||
@@ -347,8 +349,13 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
|||||||
#---- TitlePane ----
|
#---- TitlePane ----
|
||||||
|
|
||||||
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
||||||
TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
TitlePane.buttonHoverBackground = darken($TitlePane.background,5%,derived)
|
||||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,8%,derived)
|
TitlePane.buttonPressedBackground = darken($TitlePane.background,3%,derived)
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
[linux]TitlePane.buttonBackground = darken($TitlePane.background,5%,derived)
|
||||||
|
[linux]TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
||||||
|
[linux]TitlePane.buttonPressedBackground = darken($TitlePane.background,15%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|||||||
@@ -21,27 +21,41 @@
|
|||||||
# - https://www.formdev.com/flatlaf/properties-files/
|
# - https://www.formdev.com/flatlaf/properties-files/
|
||||||
# - https://www.formdev.com/flatlaf/how-to-customize/
|
# - https://www.formdev.com/flatlaf/how-to-customize/
|
||||||
#
|
#
|
||||||
|
# Properties in this file are applied in following order:
|
||||||
|
# 1. properties without '{...}' and without '[...]' prefix
|
||||||
|
# 2. properties specified in .theme.json file
|
||||||
|
# 3. properties starting with '{*}'
|
||||||
|
# 4. properties starting with '{*-light}' or '{*-dark}'
|
||||||
|
# 5. properties starting with '{author-<author>}',
|
||||||
|
# where '<author>' is replaced with "author" value from .theme.json file
|
||||||
|
# 6. properties starting with '{<name>---<author>}',
|
||||||
|
# where '<name>' and '<author>' are replaced with "name" and "author" values from .theme.json file
|
||||||
|
# 7. properties starting with '{<name>}',
|
||||||
|
# where '<name>' is replaced with "name" value from .theme.json file
|
||||||
|
# 8. properties with '[...]' prefix
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
#---- system colors ----
|
#---- system colors ----
|
||||||
|
|
||||||
# fix (most) system colors because they are usually not set in .json files
|
# fix (most) system colors because they are usually not set in .json files
|
||||||
desktop = lazy(TextField.background)
|
desktop = $TextField.background
|
||||||
activeCaptionText = lazy(TextField.foreground)
|
activeCaptionText = $TextField.foreground
|
||||||
inactiveCaptionText = lazy(TextField.foreground)
|
inactiveCaptionText = $TextField.foreground
|
||||||
window = lazy(Panel.background)
|
window = $Panel.background
|
||||||
windowBorder = lazy(TextField.foreground)
|
windowBorder = $TextField.foreground
|
||||||
windowText = lazy(TextField.foreground)
|
windowText = $TextField.foreground
|
||||||
menu = lazy(Menu.background)
|
menu = $Menu.background
|
||||||
menuText = lazy(Menu.foreground)
|
menuText = $Menu.foreground
|
||||||
text = lazy(TextField.background)
|
text = $TextField.background
|
||||||
textText = lazy(TextField.foreground)
|
textText = $TextField.foreground
|
||||||
textHighlight = lazy(TextField.selectionBackground)
|
textHighlight = $TextField.selectionBackground
|
||||||
textHighlightText = lazy(TextField.selectionForeground)
|
textHighlightText = $TextField.selectionForeground
|
||||||
textInactiveText = lazy(TextField.inactiveForeground)
|
textInactiveText = $TextField.inactiveForeground
|
||||||
control = lazy(Panel.background)
|
control = $Panel.background
|
||||||
controlText = lazy(TextField.foreground)
|
controlText = $TextField.foreground
|
||||||
info = lazy(ToolTip.background)
|
info = $ToolTip.background
|
||||||
infoText = lazy(ToolTip.foreground)
|
infoText = $ToolTip.foreground
|
||||||
|
|
||||||
|
|
||||||
#---- variables ----
|
#---- variables ----
|
||||||
@@ -49,26 +63,13 @@ infoText = lazy(ToolTip.foreground)
|
|||||||
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
|
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
|
||||||
@accentColor = null
|
@accentColor = null
|
||||||
|
|
||||||
|
# use same accent color for checkmark, slider, tab underline, etc.
|
||||||
|
@accentBase2Color = @accentBaseColor
|
||||||
|
|
||||||
# use fixed color because it is used in borders
|
# use fixed color because it is used in borders
|
||||||
@cellFocusColor = #222
|
@cellFocusColor = #222
|
||||||
|
|
||||||
|
|
||||||
#---- Button ----
|
|
||||||
|
|
||||||
Button.startBackground = $Button.background
|
|
||||||
Button.endBackground = $Button.background
|
|
||||||
Button.startBorderColor = $Button.borderColor
|
|
||||||
Button.endBorderColor = $Button.borderColor
|
|
||||||
|
|
||||||
Button.default.startBackground = $Button.default.background
|
|
||||||
Button.default.endBackground = $Button.default.background
|
|
||||||
Button.default.startBorderColor = $Button.default.borderColor
|
|
||||||
Button.default.endBorderColor = $Button.default.borderColor
|
|
||||||
|
|
||||||
Button.hoverBorderColor = null
|
|
||||||
Button.default.hoverBorderColor = null
|
|
||||||
|
|
||||||
|
|
||||||
#---- CheckBoxMenuItem ----
|
#---- CheckBoxMenuItem ----
|
||||||
|
|
||||||
# colors from intellij/checkmark.svg and darcula/checkmark.svg
|
# colors from intellij/checkmark.svg and darcula/checkmark.svg
|
||||||
@@ -76,34 +77,33 @@ Button.default.hoverBorderColor = null
|
|||||||
[dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9
|
[dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
|
||||||
|
|
||||||
Component.accentColor = lazy(ProgressBar.foreground)
|
|
||||||
|
|
||||||
|
|
||||||
#---- HelpButton ----
|
|
||||||
|
|
||||||
HelpButton.hoverBorderColor = null
|
|
||||||
|
|
||||||
|
|
||||||
#---- Slider ----
|
#---- Slider ----
|
||||||
|
|
||||||
Slider.focusedColor = fade($Component.focusColor,40%,derived)
|
# this "reverses" definition in FlatLightLaf/FlatDarkLaf.properties
|
||||||
|
Slider.trackValueColor = $Slider.thumbColor
|
||||||
|
Slider.thumbColor = @accentSliderColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- Spinner ----
|
||||||
|
|
||||||
|
# Spinner arrow button always has same colors as ComboBox arrow button
|
||||||
|
Spinner.buttonBackground = $ComboBox.buttonEditableBackground
|
||||||
|
Spinner.buttonArrowColor = $ComboBox.buttonArrowColor
|
||||||
|
Spinner.buttonDisabledArrowColor = $ComboBox.buttonDisabledArrowColor
|
||||||
|
|
||||||
|
|
||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
|
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
|
||||||
[light]TabbedPane.inactiveUnderlineColor = #9ca7b8
|
{*-light}TabbedPane.inactiveUnderlineColor = #9ca7b8
|
||||||
[dark]TabbedPane.inactiveUnderlineColor = #747a80
|
{*-dark}TabbedPane.inactiveUnderlineColor = #747a80
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|
||||||
ToggleButton.startBackground = $ToggleButton.background
|
{*}ToggleButton.background = $Button.background
|
||||||
ToggleButton.endBackground = $ToggleButton.background
|
{*-dark}ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived)
|
||||||
[dark]ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived)
|
{*-dark}ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived)
|
||||||
[dark]ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived)
|
|
||||||
|
|
||||||
|
|
||||||
#---- theme specific ----
|
#---- theme specific ----
|
||||||
@@ -112,357 +112,434 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
|
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
|
||||||
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
|
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
|
||||||
|
|
||||||
@ijTextBackgroundL3 = lighten(Panel.background,3%,lazy)
|
@ijSeparatorLight = shade(@background,15%)
|
||||||
@ijTextBackgroundL4 = lighten(Panel.background,4%,lazy)
|
@ijSeparatorDark = tint(@background,25%)
|
||||||
|
|
||||||
[Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
@ijTextBackgroundL3 = lighten($Panel.background,3%)
|
||||||
[Arc_Theme]PopupMenu.foreground = lazy(MenuItem.foreground)
|
@ijTextBackgroundL4 = lighten($Panel.background,4%)
|
||||||
[Arc_Theme]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
|
||||||
[Arc_Theme]ProgressBar.selectionBackground = #000
|
|
||||||
[Arc_Theme]ProgressBar.selectionForeground = #fff
|
|
||||||
[Arc_Theme]List.selectionInactiveForeground = #fff
|
|
||||||
[Arc_Theme]Table.selectionInactiveForeground = #fff
|
|
||||||
[Arc_Theme]Tree.selectionInactiveForeground = #fff
|
|
||||||
|
|
||||||
[Arc_Theme_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme}@selectionInactiveForeground = @selectionForeground
|
||||||
[Arc_Theme_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme}CheckBoxMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme}PopupMenu.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_-_Orange]ProgressBar.selectionBackground = #000
|
{Arc_Theme}RadioButtonMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_-_Orange]ProgressBar.selectionForeground = #fff
|
|
||||||
[Arc_Theme_-_Orange]List.selectionInactiveForeground = #fff
|
|
||||||
[Arc_Theme_-_Orange]Table.selectionInactiveForeground = #fff
|
|
||||||
[Arc_Theme_-_Orange]Tree.selectionInactiveForeground = #fff
|
|
||||||
|
|
||||||
[Arc_Theme_Dark]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_-_Orange}@selectionInactiveForeground = @selectionForeground
|
||||||
[Arc_Theme_Dark]PopupMenu.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_-_Orange}PopupMenu.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark]ProgressBar.selectionBackground = #ddd
|
{Arc_Theme_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark]ProgressBar.selectionForeground = #ddd
|
|
||||||
[Arc_Theme_Dark]ToolBar.separatorColor = lazy(Separator.foreground)
|
|
||||||
|
|
||||||
[Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_Dark}CheckBoxMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_Dark}PopupMenu.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
{Arc_Theme_Dark}RadioButtonMenuItem.foreground = $MenuItem.foreground
|
||||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionBackground = #ddd
|
{Arc_Theme_Dark}ToolBar.background = @background
|
||||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionForeground = #fff
|
|
||||||
[Arc_Theme_Dark_-_Orange]ToolBar.separatorColor = lazy(Separator.foreground)
|
|
||||||
|
|
||||||
[Carbon]Table.selectionBackground = lazy(List.selectionBackground)
|
{Arc_Theme_Dark_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground
|
||||||
[Carbon]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
{Arc_Theme_Dark_-_Orange}PopupMenu.foreground = $MenuItem.foreground
|
||||||
[Carbon]TextField.background = @ijTextBackgroundL4
|
{Arc_Theme_Dark_-_Orange}ProgressBar.selectionForeground = #fff
|
||||||
|
{Arc_Theme_Dark_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground
|
||||||
|
{Arc_Theme_Dark_-_Orange}ToolBar.background = @background
|
||||||
|
|
||||||
[Cobalt_2]Component.accentColor = lazy(Component.focusColor)
|
{Carbon}Separator.foreground = @ijSeparatorDark
|
||||||
[Cobalt_2]CheckBox.icon.background = #002946
|
{Carbon}ToolBar.separatorColor = $Separator.foreground
|
||||||
[Cobalt_2]CheckBox.icon.checkmarkColor = #002946
|
{Carbon}Table.selectionBackground = $List.selectionBackground
|
||||||
[Cobalt_2]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{Carbon}TextField.background = @ijTextBackgroundL4
|
||||||
[Cobalt_2]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
|
||||||
[Cobalt_2]ComboBox.background = @ijTextBackgroundL3
|
|
||||||
[Cobalt_2]ComboBox.buttonBackground = @ijTextBackgroundL3
|
|
||||||
[Cobalt_2]TextField.background = @ijTextBackgroundL3
|
|
||||||
[Cobalt_2]Table.background = lazy(List.background)
|
|
||||||
[Cobalt_2]Tree.background = lazy(List.background)
|
|
||||||
|
|
||||||
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
{Cobalt_2}@accentBaseColor = $ColorPalette.hue3
|
||||||
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
{Cobalt_2}CheckBox.icon.background = @background
|
||||||
|
{Cobalt_2}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
|
{Cobalt_2}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
{Cobalt_2}ComboBox.background = @ijTextBackgroundL3
|
||||||
|
{Cobalt_2}Slider.thumbColor = $ProgressBar.foreground
|
||||||
|
{Cobalt_2}Slider.disabledTrackColor = $Separator.foreground
|
||||||
|
{Cobalt_2}TextField.background = @ijTextBackgroundL3
|
||||||
|
{Cobalt_2}Table.background = $List.background
|
||||||
|
{Cobalt_2}Tree.background = $List.background
|
||||||
|
|
||||||
[Dark_Flat_Theme]*.inactiveForeground = #808080
|
{Cyan_light}@disabledForeground = tint(@foreground,30%)
|
||||||
[Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
|
{Cyan_light}*.disabledText = @disabledForeground
|
||||||
[Dark_Flat_Theme]TableHeader.background = #3B3B3B
|
{Cyan_light}*.disabledForeground = @disabledForeground
|
||||||
[Dark_Flat_Theme]TextPane.foreground = lazy(TextField.foreground)
|
{Cyan_light}*.inactiveForeground = @disabledForeground
|
||||||
[Dark_Flat_Theme]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
{Cyan_light}Button.background = @buttonBackground
|
||||||
[Dark_Flat_Theme]List.selectionForeground = lazy(Tree.selectionForeground)
|
{Cyan_light}MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||||
[Dark_Flat_Theme]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
{Cyan_light}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||||
[Dark_Flat_Theme]Separator.foreground = lazy(ToolBar.separatorColor)
|
|
||||||
|
|
||||||
[Dark_purple]Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
{Dark_Flat_Theme}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
|
{Dark_Flat_Theme}@disabledForeground = #808080
|
||||||
|
{Dark_Flat_Theme}*.disabledText = @disabledForeground
|
||||||
|
{Dark_Flat_Theme}*.disabledForeground = @disabledForeground
|
||||||
|
{Dark_Flat_Theme}*.inactiveForeground = @disabledForeground
|
||||||
|
{Dark_Flat_Theme}TableHeader.background = #3B3B3B
|
||||||
|
{Dark_Flat_Theme}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
|
{Dark_Flat_Theme}ComboBox.background = $TextField.background
|
||||||
|
{Dark_Flat_Theme}ComboBox.buttonBackground = $ComboBox.background
|
||||||
|
{Dark_Flat_Theme}List.selectionForeground = $Tree.selectionForeground
|
||||||
|
{Dark_Flat_Theme}ProgressBar.selectionForeground = @foreground
|
||||||
|
{Dark_Flat_Theme}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
|
{Dark_Flat_Theme}Separator.foreground = @ijSeparatorDark
|
||||||
|
{Dark_Flat_Theme}Slider.trackColor = $ProgressBar.background
|
||||||
|
{Dark_Flat_Theme}Slider.thumbColor = fade($ProgressBar.foreground,100%)
|
||||||
|
{Dark_Flat_Theme}TextPane.foreground = $TextField.foreground
|
||||||
|
{Dark_Flat_Theme}ToggleButton.foreground = $Button.foreground
|
||||||
|
|
||||||
[Dracula---Zihan_Ma]Component.accentColor = lazy(Component.focusColor)
|
{Dracula---Zihan_Ma}CheckBox.icon.background = @background
|
||||||
[Dracula---Zihan_Ma]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
{Dracula---Zihan_Ma}ComboBox.selectionBackground = $List.selectionBackground
|
||||||
[Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
|
{Dracula---Zihan_Ma}ProgressBar.selectionBackground = #fff
|
||||||
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
{Dracula---Zihan_Ma}ProgressBar.selectionForeground = #fff
|
||||||
|
{Dracula---Zihan_Ma}Slider.trackColor = $?ColorPalette.selectionBackground
|
||||||
|
{Dracula---Zihan_Ma}ToggleButton.foreground = $Button.foreground
|
||||||
|
|
||||||
[Gradianto_Dark_Fuchsia]*.selectionBackground = #8452a7
|
{Gradianto_Dark_Fuchsia}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gradianto_Dark_Fuchsia]*.selectionInactiveBackground = #562C6A
|
{Gradianto_Dark_Fuchsia}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{Gradianto_Dark_Fuchsia}TextField.background = @ijTextBackgroundL4
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{Gradianto_Dark_Fuchsia}Tree.background = $List.background
|
||||||
[Gradianto_Dark_Fuchsia]TextField.background = @ijTextBackgroundL4
|
{Gradianto_Dark_Fuchsia}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
[Gradianto_Dark_Fuchsia]Tree.background = lazy(List.background)
|
{Gradianto_Dark_Fuchsia}Separator.foreground = @ijSeparatorDark
|
||||||
[Gradianto_Dark_Fuchsia]Separator.foreground = lazy(ScrollBar.track)
|
{Gradianto_Dark_Fuchsia}ToolBar.separatorColor = $Separator.foreground
|
||||||
[Gradianto_Dark_Fuchsia]ToolBar.separatorColor = lazy(ScrollBar.track)
|
{Gradianto_Dark_Fuchsia}ProgressBar.background = $ScrollBar.track
|
||||||
[Gradianto_Dark_Fuchsia]ProgressBar.background = lazy(ScrollBar.track)
|
{Gradianto_Dark_Fuchsia}Slider.trackColor = $ScrollBar.track
|
||||||
[Gradianto_Dark_Fuchsia]Slider.trackColor = lazy(ScrollBar.track)
|
|
||||||
|
|
||||||
[Gradianto_Deep_Ocean]TextField.background = @ijTextBackgroundL3
|
{Gradianto_Deep_Ocean}Separator.foreground = @ijSeparatorDark
|
||||||
[Gradianto_Deep_Ocean]Tree.background = lazy(List.background)
|
{Gradianto_Deep_Ocean}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
{Gradianto_Deep_Ocean}TextField.background = @ijTextBackgroundL3
|
||||||
|
{Gradianto_Deep_Ocean}Tree.background = $List.background
|
||||||
|
|
||||||
[Gradianto_Midnight_Blue]ScrollBar.thumb = #533B6B
|
{Gradianto_Midnight_Blue}ScrollBar.thumb = #533B6B
|
||||||
[Gradianto_Midnight_Blue]Table.selectionForeground = lazy(List.selectionForeground)
|
{Gradianto_Midnight_Blue}Separator.foreground = @ijSeparatorDark
|
||||||
[Gradianto_Midnight_Blue]TextField.background = @ijTextBackgroundL4
|
{Gradianto_Midnight_Blue}ToolBar.separatorColor = $Separator.foreground
|
||||||
[Gradianto_Midnight_Blue]Tree.background = lazy(List.background)
|
{Gradianto_Midnight_Blue}Table.selectionForeground = $List.selectionForeground
|
||||||
|
{Gradianto_Midnight_Blue}TextField.background = @ijTextBackgroundL4
|
||||||
|
{Gradianto_Midnight_Blue}Tree.background = $List.background
|
||||||
|
|
||||||
[Gradianto_Nature_Green]Table.selectionForeground = lazy(List.selectionForeground)
|
{Gradianto_Nature_Green}Separator.foreground = @ijSeparatorDark
|
||||||
[Gradianto_Nature_Green]TextField.background = @ijTextBackgroundL4
|
{Gradianto_Nature_Green}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
{Gradianto_Nature_Green}Table.selectionForeground = $List.selectionForeground
|
||||||
|
{Gradianto_Nature_Green}TextField.background = @ijTextBackgroundL4
|
||||||
|
|
||||||
[Gray]Separator.foreground = lazy(Slider.trackColor)
|
{Gray}@disabledForeground = tint(@foreground,40%)
|
||||||
[Gray]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Gray}*.disabledText = @disabledForeground
|
||||||
|
{Gray}*.disabledForeground = @disabledForeground
|
||||||
|
{Gray}*.inactiveForeground = @disabledForeground
|
||||||
|
{Gray}Button.background = @buttonBackground
|
||||||
|
{Gray}Separator.foreground = @ijSeparatorLight
|
||||||
|
{Gray}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
|
||||||
[Gruvbox_Dark_Hard]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{Gruvbox_Dark_Hard}@accentBaseColor = #4B6EAF
|
||||||
[Gruvbox_Dark_Hard]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
{Gruvbox_Dark_Hard}ComboBox.background = @ijTextBackgroundL3
|
||||||
[Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
{Gruvbox_Dark_Hard}ComboBox.buttonBackground = $ComboBox.background
|
||||||
[Gruvbox_Dark_Hard]ComboBox.background = @ijTextBackgroundL3
|
{Gruvbox_Dark_Hard}TextField.background = @ijTextBackgroundL3
|
||||||
[Gruvbox_Dark_Hard]ComboBox.buttonBackground = @ijTextBackgroundL3
|
|
||||||
[Gruvbox_Dark_Hard]TextField.background = @ijTextBackgroundL3
|
|
||||||
|
|
||||||
[Gruvbox_Dark_Medium]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{Hiberbee_Dark}@disabledForeground = $ColorPalette.light3
|
||||||
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
{Hiberbee_Dark}*.disabledText = @disabledForeground
|
||||||
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
{Hiberbee_Dark}*.disabledForeground = @disabledForeground
|
||||||
[Gruvbox_Dark_Medium]ComboBox.background = @ijTextBackgroundL3
|
{Hiberbee_Dark}*.inactiveForeground = @disabledForeground
|
||||||
[Gruvbox_Dark_Medium]ComboBox.buttonBackground = @ijTextBackgroundL3
|
{Hiberbee_Dark}List.selectionInactiveBackground = $Table.selectionInactiveBackground
|
||||||
[Gruvbox_Dark_Medium]TextField.background = @ijTextBackgroundL3
|
{Hiberbee_Dark}ProgressBar.background = $Separator.foreground
|
||||||
|
{Hiberbee_Dark}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
|
{Hiberbee_Dark}Slider.trackColor = $ColorPalette.light1
|
||||||
|
{Hiberbee_Dark}Slider.trackColor = $ColorPalette.dark10
|
||||||
|
{Hiberbee_Dark}Slider.thumbColor = @accentBaseColor
|
||||||
|
{Hiberbee_Dark}ToggleButton.foreground = $Button.foreground
|
||||||
|
{Hiberbee_Dark}ToolBar.background = @background
|
||||||
|
|
||||||
[Gruvbox_Dark_Soft]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{High_Contrast}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
[Gruvbox_Dark_Soft]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{High_Contrast}Slider.thumbBorderColor = $Slider.thumbColor
|
||||||
[Gruvbox_Dark_Soft]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{High_Contrast}Slider.focusedThumbBorderColor = @background
|
||||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
{High_Contrast}Slider.focusedColor = $Component.focusColor
|
||||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
{High_Contrast}Slider.focusWidth = 2
|
||||||
[Gruvbox_Dark_Soft]ComboBox.background = @ijTextBackgroundL3
|
{High_Contrast}ToggleButton.selectedBackground = @selectionBackground
|
||||||
[Gruvbox_Dark_Soft]ComboBox.buttonBackground = @ijTextBackgroundL3
|
{High_Contrast}ToggleButton.selectedForeground = @selectionForeground
|
||||||
[Gruvbox_Dark_Soft]TextField.background = @ijTextBackgroundL3
|
{High_Contrast}ToggleButton.disabledSelectedBackground = shade(@selectionBackground,50%)
|
||||||
|
{High_Contrast}ToggleButton.toolbar.selectedBackground = @selectionBackground
|
||||||
[Hiberbee_Dark]*.disabledForeground = #7F7E7D
|
{High_Contrast}[style]Button.inTextField = \
|
||||||
[Hiberbee_Dark]*.disabledText = #7F7E7D
|
|
||||||
[Hiberbee_Dark]*.inactiveForeground = #7F7E7D
|
|
||||||
[Hiberbee_Dark]ProgressBar.background = lazy(Separator.foreground)
|
|
||||||
[Hiberbee_Dark]Slider.trackColor = lazy(Separator.foreground)
|
|
||||||
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
|
||||||
[Hiberbee_Dark]TabbedPane.selectedBackground = #434241
|
|
||||||
[Hiberbee_Dark]TabbedPane.selectedForeground = #70D7FF
|
|
||||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
|
||||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
|
||||||
[Hiberbee_Dark]Table.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
|
||||||
[Hiberbee_Dark]Tree.selectionBackground = lazy(List.selectionBackground)
|
|
||||||
[Hiberbee_Dark]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
|
||||||
|
|
||||||
[High_contrast]Component.accentColor = lazy(Component.focusColor)
|
|
||||||
[High_contrast]ToggleButton.selectedBackground = #fff
|
|
||||||
[High_contrast]ToggleButton.selectedForeground = #000
|
|
||||||
[High_contrast]ToggleButton.disabledSelectedBackground = #444
|
|
||||||
[High_contrast]ToggleButton.toolbar.selectedBackground = #fff
|
|
||||||
[High_contrast][style]Button.inTextField = \
|
|
||||||
toolbar.hoverBackground: #444; \
|
toolbar.hoverBackground: #444; \
|
||||||
toolbar.pressedBackground: #666; \
|
toolbar.pressedBackground: #666; \
|
||||||
toolbar.selectedBackground: #fff
|
toolbar.selectedBackground: @selectionBackground
|
||||||
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
|
|
||||||
|
|
||||||
[Light_Flat]*.disabledForeground = #8C8C8C
|
{Light_Flat}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
[Light_Flat]*.inactiveForeground = #8C8C8C
|
{Light_Flat}@accentFocusColor = lighten(@accentBaseColor,15%)
|
||||||
[Light_Flat]CheckBox.icon[filled].background = #fff
|
{Light_Flat}@disabledForeground = #808080
|
||||||
[Light_Flat]CheckBox.icon[filled].checkmarkColor = #fff
|
{Light_Flat}*.disabledText = @disabledForeground
|
||||||
[Light_Flat]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{Light_Flat}*.disabledForeground = @disabledForeground
|
||||||
[Light_Flat]ComboBox.background = lazy(ComboBox.editableBackground)
|
{Light_Flat}*.inactiveForeground = @disabledForeground
|
||||||
[Light_Flat]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
|
{Light_Flat}CheckBox.icon[filled].background = #fff
|
||||||
[Light_Flat]Separator.foreground = lazy(ToolBar.separatorColor)
|
{Light_Flat}CheckBox.icon[filled].checkmarkColor = #fff
|
||||||
[Light_Flat]TableHeader.background = #E5E5E9
|
{Light_Flat}ComboBox.background = $ComboBox.editableBackground
|
||||||
[Light_Flat]TextPane.foreground = lazy(TextField.foreground)
|
{Light_Flat}ComboBox.buttonBackground = $ComboBox.background
|
||||||
[Light_Flat]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
{Light_Flat}ProgressBar.selectionForeground = @foreground
|
||||||
[Light_Flat]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
{Light_Flat}Separator.foreground = @ijSeparatorLight
|
||||||
|
{Light_Flat}TableHeader.background = #E5E5E9
|
||||||
|
{Light_Flat}TextPane.foreground = $TextField.foreground
|
||||||
|
{Light_Flat}ToggleButton.foreground = $Button.foreground
|
||||||
|
{Light_Flat}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
|
{Light_Flat}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
|
|
||||||
[Monocai]Button.default.foreground = #2D2A2F
|
{Monocai}@accentUnderlineColor = @accentBaseColor
|
||||||
[Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{Monocai}*.acceleratorForeground = @menuAcceleratorForeground
|
||||||
[Monocai]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{Monocai}*.acceleratorSelectionForeground = @menuAcceleratorSelectionForeground
|
||||||
@Monocai.acceleratorForeground = lazy(MenuItem.disabledForeground)
|
{Monocai}Button.default.foreground = @background
|
||||||
@Monocai.acceleratorSelectionForeground = lighten(MenuItem.disabledForeground,10%,lazy)
|
{Monocai}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Monocai]CheckBoxMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
{Monocai}TabbedPane.underlineColor = @accentUnderlineColor
|
||||||
[Monocai]CheckBoxMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
{Monocai}TextField.background = @ijTextBackgroundL4
|
||||||
[Monocai]Menu.acceleratorForeground = @Monocai.acceleratorForeground
|
@Monocai.selectionBackground = $TextField.selectionBackground
|
||||||
[Monocai]Menu.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
{Monocai}ComboBox.selectionBackground = @Monocai.selectionBackground
|
||||||
[Monocai]MenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
{Monocai}List.selectionBackground = @Monocai.selectionBackground
|
||||||
[Monocai]MenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
{Monocai}Table.selectionBackground = @Monocai.selectionBackground
|
||||||
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
{Monocai}Tree.selectionBackground = @Monocai.selectionBackground
|
||||||
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
@Monocai.selectionInactiveBackground = $MenuItem.selectionBackground
|
||||||
[Monocai]TextField.background = @ijTextBackgroundL4
|
{Monocai}List.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
@Monocai.selectionBackground = lazy(TextField.selectionBackground)
|
{Monocai}Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
[Monocai]ComboBox.selectionBackground = @Monocai.selectionBackground
|
{Monocai}Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
[Monocai]List.selectionBackground = @Monocai.selectionBackground
|
|
||||||
[Monocai]Table.selectionBackground = @Monocai.selectionBackground
|
|
||||||
[Monocai]Tree.selectionBackground = @Monocai.selectionBackground
|
|
||||||
@Monocai.selectionInactiveBackground = lazy(MenuItem.selectionBackground)
|
|
||||||
[Monocai]List.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
|
||||||
[Monocai]Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
|
||||||
[Monocai]Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
|
||||||
|
|
||||||
[Monokai_Pro---Subtheme]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
{Monokai_Pro---Subtheme}@disabledForeground = shade(@foreground,40%)
|
||||||
[Monokai_Pro---Subtheme]Tree.selectionBackground = lazy(List.selectionBackground)
|
{Monokai_Pro---Subtheme}*.disabledText = @disabledForeground
|
||||||
[Monokai_Pro---Subtheme]Separator.foreground = lazy(Slider.trackColor)
|
{Monokai_Pro---Subtheme}*.disabledForeground = @disabledForeground
|
||||||
[Monokai_Pro---Subtheme]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Monokai_Pro---Subtheme}*.inactiveForeground = @disabledForeground
|
||||||
|
{Monokai_Pro---Subtheme}ProgressBar.selectionBackground = #fff
|
||||||
|
{Monokai_Pro---Subtheme}Table.selectionInactiveForeground = $List.selectionInactiveForeground
|
||||||
|
{Monokai_Pro---Subtheme}Tree.selectionBackground = $List.selectionBackground
|
||||||
|
{Monokai_Pro---Subtheme}ToggleButton.foreground = $Button.foreground
|
||||||
|
{Monokai_Pro---Subtheme}Separator.foreground = @ijSeparatorDark
|
||||||
|
{Monokai_Pro---Subtheme}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
{Monokai_Pro---Subtheme}ToolBar.background = @background
|
||||||
|
|
||||||
[Nord]*.inactiveForeground = #616E88
|
{Nord}@disabledForeground = #616E88
|
||||||
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{Nord}*.disabledText = @disabledForeground
|
||||||
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{Nord}*.disabledForeground = @disabledForeground
|
||||||
[Nord]List.selectionBackground = lazy(Tree.selectionBackground)
|
{Nord}*.inactiveForeground = @disabledForeground
|
||||||
[Nord]List.selectionForeground = lazy(Tree.selectionForeground)
|
{Nord}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Nord]Table.selectionBackground = lazy(Tree.selectionBackground)
|
{Nord}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[Nord]Table.selectionForeground = lazy(Tree.selectionForeground)
|
{Nord}RadioButtonMenuItem.selectionBackground = $MenuItem.selectionBackground
|
||||||
[Nord]TextField.selectionBackground = lazy(Tree.selectionBackground)
|
{Nord}ProgressBar.selectionBackground = @foreground
|
||||||
[Nord]TextField.selectionForeground = lazy(Tree.selectionForeground)
|
{Nord}ProgressBar.selectionForeground = @background
|
||||||
[Nord]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
{Nord}List.selectionBackground = $Tree.selectionBackground
|
||||||
|
{Nord}List.selectionForeground = $Tree.selectionForeground
|
||||||
|
{Nord}Table.selectionBackground = $Tree.selectionBackground
|
||||||
|
{Nord}Table.selectionForeground = $Tree.selectionForeground
|
||||||
|
{Nord}TextField.selectionBackground = $Tree.selectionBackground
|
||||||
|
{Nord}TextField.selectionForeground = $Tree.selectionForeground
|
||||||
|
{Nord}Tree.selectionInactiveForeground = $List.selectionInactiveForeground
|
||||||
|
|
||||||
[NotReallyMDTheme]*.selectionInactiveBackground = #21384E
|
{NotReallyMDTheme}*.selectionInactiveBackground = #21384E
|
||||||
[NotReallyMDTheme]ToolBar.separatorColor = lazy(Separator.foreground)
|
{NotReallyMDTheme}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
|
||||||
[One_Dark]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
{One_Dark}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[One_Dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{One_Dark}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{One_Dark}ProgressBar.background = $Separator.foreground
|
||||||
[One_Dark]ProgressBar.background = lazy(Separator.foreground)
|
{One_Dark}ProgressBar.selectionForeground = #fff
|
||||||
[One_Dark]Slider.trackColor = lazy(Separator.foreground)
|
{One_Dark}Table.background = $Tree.background
|
||||||
[One_Dark]Slider.focusedColor = fade(#568af2,40%)
|
{One_Dark}Table.selectionBackground = $Tree.selectionBackground
|
||||||
[One_Dark]Table.background = lazy(Tree.background)
|
{One_Dark}TextField.selectionBackground = $List.selectionBackground
|
||||||
[One_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
|
{One_Dark}Tree.selectionForeground = $List.selectionForeground
|
||||||
[One_Dark]TextField.selectionBackground = lazy(List.selectionBackground)
|
|
||||||
[One_Dark]Tree.selectionForeground = lazy(List.selectionForeground)
|
|
||||||
|
|
||||||
[Solarized_Dark---4lex4]*.inactiveForeground = #657B83
|
{Solarized_Dark---4lex4}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{Solarized_Dark---4lex4}*.acceleratorForeground = @menuAcceleratorForeground
|
||||||
[Solarized_Dark---4lex4]ComboBox.background = lazy(ComboBox.editableBackground)
|
{Solarized_Dark---4lex4}ComboBox.background = $ComboBox.editableBackground
|
||||||
[Solarized_Dark---4lex4]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
|
{Solarized_Dark---4lex4}ComboBox.buttonBackground = $ComboBox.editableBackground
|
||||||
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
{Solarized_Dark---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator
|
||||||
[Solarized_Dark---4lex4]ToolBar.separatorColor = lazy(Separator.foreground)
|
|
||||||
|
|
||||||
[Solarized_Light---4lex4]*.inactiveForeground = #839496
|
{Solarized_Light---4lex4}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
[Solarized_Light---4lex4]Button.default.hoverBackground = darken($Button.default.background,3%,derived)
|
{Solarized_Light---4lex4}Slider.thumbColor = $ProgressBar.foreground
|
||||||
[Solarized_Light---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
{Solarized_Light---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator
|
||||||
|
|
||||||
[Spacegray]ComboBox.background = @ijTextBackgroundL4
|
{Spacegray}ComboBox.background = @ijTextBackgroundL4
|
||||||
[Spacegray]ComboBox.buttonBackground = @ijTextBackgroundL4
|
{Spacegray}ComboBox.buttonBackground = $ComboBox.background
|
||||||
[Spacegray]TextField.background = @ijTextBackgroundL4
|
{Spacegray}TextField.background = @ijTextBackgroundL4
|
||||||
[Spacegray]TextField.selectionBackground = lazy(Tree.selectionBackground)
|
|
||||||
[Spacegray]TextField.selectionForeground = lazy(Tree.selectionForeground)
|
|
||||||
|
|
||||||
[vuesion-theme]*.disabledForeground = #8C8C8C
|
{vuesion-theme}@accentBaseColor = $TabbedPane.underlineColor
|
||||||
[vuesion-theme]*.disabledText = #8C8C8C
|
{vuesion-theme}@disabledForeground = #8C8C8C
|
||||||
[vuesion-theme]*.inactiveForeground = #8C8C8C
|
{vuesion-theme}*.disabledText = @disabledForeground
|
||||||
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
{vuesion-theme}*.disabledForeground = @disabledForeground
|
||||||
[vuesion-theme]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
{vuesion-theme}*.inactiveForeground = @disabledForeground
|
||||||
[vuesion-theme]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
{vuesion-theme}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[vuesion-theme]Slider.trackValueColor = #ececee
|
{vuesion-theme}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[vuesion-theme]Slider.trackColor = #303a45
|
{vuesion-theme}ProgressBar.background = #303a45
|
||||||
[vuesion-theme]Slider.thumbColor = #ececee
|
{vuesion-theme}ProgressBar.foreground = #ececee
|
||||||
[vuesion-theme]Slider.focusedColor = fade(#ececee,20%)
|
{vuesion-theme}Slider.thumbColor = #ececee
|
||||||
[vuesion-theme]ComboBox.background = @ijTextBackgroundL4
|
{vuesion-theme}Slider.focusedColor = fade($Slider.thumbColor,20%)
|
||||||
[vuesion-theme]ComboBox.buttonBackground = @ijTextBackgroundL4
|
{vuesion-theme}ComboBox.background = @ijTextBackgroundL4
|
||||||
[vuesion-theme]TextField.background = @ijTextBackgroundL4
|
{vuesion-theme}ComboBox.buttonBackground = $ComboBox.background
|
||||||
[vuesion-theme]TextField.selectionBackground = lighten(#303A45,15%)
|
{vuesion-theme}TextField.background = @ijTextBackgroundL4
|
||||||
|
{vuesion-theme}TextField.selectionBackground = lighten(#303A45,15%)
|
||||||
|
|
||||||
[Xcode-Dark]TextField.background = @ijTextBackgroundL4
|
{Xcode-Dark}@accentBaseColor = $List.selectionBackground
|
||||||
|
{Xcode-Dark}TextField.background = @ijTextBackgroundL4
|
||||||
|
|
||||||
|
|
||||||
# Material Theme UI Lite
|
# Material Theme UI Lite
|
||||||
|
|
||||||
[light][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundD10
|
{author-Mallowigi}[light]controlHighlight = lighten($controlShadow,8%)
|
||||||
[light][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10
|
{author-Mallowigi}[light]controlLtHighlight = lighten($controlShadow,15%)
|
||||||
[dark][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
{author-Mallowigi}[light]controlDkShadow = darken($controlShadow,15%)
|
||||||
[dark][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
{author-Mallowigi}[dark]controlHighlight = darken($controlShadow,10%)
|
||||||
|
{author-Mallowigi}[dark]controlLtHighlight = darken($controlShadow,15%)
|
||||||
|
{author-Mallowigi}[dark]controlDkShadow = lighten($controlShadow,10%)
|
||||||
|
|
||||||
[author-Mallowigi]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
{author-Mallowigi}Button.hoverBorderColor = $Button.focusedBorderColor
|
||||||
|
{author-Mallowigi}HelpButton.hoverBorderColor = $Button.focusedBorderColor
|
||||||
|
|
||||||
[Arc_Dark]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
{author-Mallowigi}[light]ToggleButton.selectedForeground = #000
|
||||||
[Arc_Dark]Table.selectionBackground = lazy(List.selectionBackground)
|
{author-Mallowigi}[dark]ToggleButton.selectedForeground = #fff
|
||||||
|
|
||||||
[Atom_One_Dark]Separator.foreground = lazy(Slider.trackColor)
|
{author-Mallowigi}[light]MenuItem.checkBackground = @ijMenuCheckBackgroundD10
|
||||||
[Atom_One_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{author-Mallowigi}[light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10
|
||||||
|
{author-Mallowigi}[dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||||
|
{author-Mallowigi}[dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||||
|
|
||||||
[Atom_One_Light]List.selectionBackground = lazy(Table.selectionBackground)
|
{author-Mallowigi}[light]Separator.foreground = @ijSeparatorLight
|
||||||
[Atom_One_Light]Tree.selectionBackground = lazy(Table.selectionBackground)
|
{author-Mallowigi}[dark]Separator.foreground = @ijSeparatorDark
|
||||||
[Atom_One_Light]TabbedPane.contentAreaColor = lazy(Separator.foreground)
|
{author-Mallowigi}ProgressBar.selectionBackground = @foreground
|
||||||
|
{author-Mallowigi}TabbedPane.selectedBackground = mix(@background,$ColorPalette.table,60%)
|
||||||
|
{author-Mallowigi}ToolBar.separatorColor = $Separator.foreground
|
||||||
|
{author-Mallowigi}Button.foreground = @foreground
|
||||||
|
{author-Mallowigi}Tree.foreground = @foreground
|
||||||
|
|
||||||
[Dracula---Mallowigi]*.selectionBackground = #44475A
|
|
||||||
[Dracula---Mallowigi]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
|
||||||
[Dracula---Mallowigi]ProgressBar.selectionBackground = #fff
|
|
||||||
[Dracula---Mallowigi]ProgressBar.selectionForeground = #fff
|
|
||||||
[Dracula---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(CheckBoxMenuItem.selectionForeground)
|
|
||||||
[Dracula---Mallowigi]Table.selectionForeground = lazy(List.selectionForeground)
|
|
||||||
[Dracula---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
|
||||||
[Dracula---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
|
||||||
|
|
||||||
[GitHub]ProgressBar.selectionBackground = #222
|
{Arc_Dark}ComboBox.selectionBackground = $List.selectionBackground
|
||||||
[GitHub]ProgressBar.selectionForeground = #222
|
{Arc_Dark}ProgressBar.selectionBackground = #fff
|
||||||
[GitHub]TextField.background = @ijTextBackgroundL3
|
{Arc_Dark}ProgressBar.selectionForeground = #fff
|
||||||
[GitHub]List.selectionBackground = lazy(Table.selectionBackground)
|
{Arc_Dark}Table.selectionBackground = $List.selectionBackground
|
||||||
[GitHub]Tree.selectionBackground = lazy(Table.selectionBackground)
|
{Arc_Dark}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
[GitHub_Dark]ComboBox.selectionBackground = lazy(Tree.selectionBackground)
|
{Atom_One_Dark}ProgressBar.selectionBackground = #fff
|
||||||
[GitHub_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
|
{Atom_One_Dark}ProgressBar.selectionForeground = #fff
|
||||||
[GitHub_Dark]Separator.foreground = lazy(Slider.trackColor)
|
{Atom_One_Dark}List.selectionBackground = $Table.selectionBackground
|
||||||
[GitHub_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Atom_One_Dark}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Atom_One_Dark}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Atom_One_Dark}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Light_Owl]CheckBoxMenuItem.selectionForeground = lazy(CheckBoxMenuItem.foreground)
|
{Atom_One_Light}@disabledForeground = shade($ColorPalette.dis,20%)
|
||||||
[Light_Owl]ComboBox.selectionForeground = lazy(ComboBox.foreground)
|
{Atom_One_Light}*.disabledText = @disabledForeground
|
||||||
[Light_Owl]List.selectionInactiveForeground = lazy(List.foreground)
|
{Atom_One_Light}*.disabledForeground = @disabledForeground
|
||||||
[Light_Owl]Menu.selectionForeground = lazy(Menu.foreground)
|
{Atom_One_Light}*.inactiveForeground = @disabledForeground
|
||||||
[Light_Owl]MenuBar.selectionForeground = lazy(MenuBar.foreground)
|
{Atom_One_Light}TabbedPane.contentAreaColor = $Separator.foreground
|
||||||
[Light_Owl]MenuItem.selectionForeground = lazy(MenuItem.foreground)
|
|
||||||
[Light_Owl]ProgressBar.selectionBackground = #111
|
|
||||||
[Light_Owl]ProgressBar.selectionForeground = #fff
|
|
||||||
[Light_Owl]Spinner.selectionForeground = lazy(Spinner.foreground)
|
|
||||||
[Light_Owl]Table.selectionForeground = lazy(Table.foreground)
|
|
||||||
[Light_Owl]TextField.selectionForeground = lazy(TextField.foreground)
|
|
||||||
[Light_Owl]TextField.background = @ijTextBackgroundL3
|
|
||||||
[Light_Owl]List.selectionBackground = lazy(Table.selectionBackground)
|
|
||||||
[Light_Owl]Tree.selectionBackground = lazy(Table.selectionBackground)
|
|
||||||
|
|
||||||
[Material_Darker]*.selectionBackground = lighten(#2D2D2D,15%)
|
{Dracula---Mallowigi}ProgressBar.selectionBackground = #fff
|
||||||
[Material_Darker]Separator.foreground = lazy(Slider.trackColor)
|
{Dracula---Mallowigi}ProgressBar.selectionForeground = #fff
|
||||||
[Material_Darker]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Dracula---Mallowigi}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{Dracula---Mallowigi}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Dracula---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Dracula---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Material_Deep_Ocean]*.selectionBackground = lighten(#222533,15%)
|
{GitHub}ProgressBar.selectionBackground = #222
|
||||||
[Material_Deep_Ocean]Separator.foreground = lazy(Slider.trackColor)
|
{GitHub}ProgressBar.selectionForeground = #222
|
||||||
[Material_Deep_Ocean]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{GitHub}TextField.background = @ijTextBackgroundL3
|
||||||
|
{GitHub}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{GitHub}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{GitHub}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{GitHub}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Material_Lighter]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
{GitHub_Dark}ComboBox.selectionBackground = $Tree.selectionBackground
|
||||||
[Material_Lighter]ProgressBar.selectionBackground = #222
|
{GitHub_Dark}ProgressBar.selectionForeground = #fff
|
||||||
[Material_Lighter]ProgressBar.selectionForeground = #fff
|
{GitHub_Dark}Slider.trackColor = lighten(#2b3036,5%)
|
||||||
[Material_Lighter]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
{GitHub_Dark}Table.selectionBackground = $Tree.selectionBackground
|
||||||
[Material_Lighter]Table.selectionBackground = lazy(List.selectionBackground)
|
{GitHub_Dark}Tree.selectionInactiveBackground = $Table.selectionInactiveBackground
|
||||||
[Material_Lighter]List.selectionForeground = lazy(Table.selectionForeground)
|
|
||||||
[Material_Lighter]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
|
|
||||||
[Material_Lighter]Tree.selectionForeground = lazy(Table.selectionForeground)
|
|
||||||
|
|
||||||
[Material_Oceanic]ProgressBar.selectionBackground = #ddd
|
{Light_Owl}@disabledForeground = shade($ColorPalette.dis,10%)
|
||||||
[Material_Oceanic]ProgressBar.selectionForeground = #ddd
|
{Light_Owl}*.disabledText = @disabledForeground
|
||||||
[Material_Oceanic]Separator.foreground = lazy(Slider.trackColor)
|
{Light_Owl}*.disabledForeground = @disabledForeground
|
||||||
[Material_Oceanic]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Light_Owl}*.inactiveForeground = @disabledForeground
|
||||||
|
{Light_Owl}CheckBoxMenuItem.selectionForeground = $CheckBoxMenuItem.foreground
|
||||||
|
{Light_Owl}ComboBox.selectionForeground = $ComboBox.foreground
|
||||||
|
{Light_Owl}List.selectionInactiveForeground = $Table.selectionInactiveForeground
|
||||||
|
{Light_Owl}Menu.selectionForeground = $Menu.foreground
|
||||||
|
{Light_Owl}MenuBar.selectionForeground = $MenuBar.foreground
|
||||||
|
{Light_Owl}MenuItem.selectionForeground = $MenuItem.foreground
|
||||||
|
{Light_Owl}Table.selectionForeground = $List.selectionForeground
|
||||||
|
{Light_Owl}TextField.selectionForeground = $TextField.foreground
|
||||||
|
{Light_Owl}TextField.background = @ijTextBackgroundL3
|
||||||
|
{Light_Owl}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{Light_Owl}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Light_Owl}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Light_Owl}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Material_Palenight]ProgressBar.selectionBackground = #ddd
|
{Material_Darker}@disabledForeground = tint($ColorPalette.dis,30%)
|
||||||
[Material_Palenight]ProgressBar.selectionForeground = #ddd
|
{Material_Darker}*.disabledText = @disabledForeground
|
||||||
[Material_Palenight]List.selectionBackground = lazy(Table.selectionBackground)
|
{Material_Darker}*.disabledForeground = @disabledForeground
|
||||||
[Material_Palenight]Tree.selectionBackground = lazy(Table.selectionBackground)
|
{Material_Darker}*.inactiveForeground = @disabledForeground
|
||||||
[Material_Palenight]Separator.foreground = lazy(Slider.trackColor)
|
{Material_Darker}*.selectionBackground = lighten($ColorPalette.tree,15%)
|
||||||
[Material_Palenight]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Material_Darker}ProgressBar.selectionForeground = #fff
|
||||||
|
{Material_Darker}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
[Monokai_Pro---Mallowigi]List.selectionForeground = lazy(Table.selectionForeground)
|
{Material_Deep_Ocean}@disabledForeground = tint($ColorPalette.dis,10%)
|
||||||
[Monokai_Pro---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
|
{Material_Deep_Ocean}*.disabledText = @disabledForeground
|
||||||
[Monokai_Pro---Mallowigi]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
{Material_Deep_Ocean}*.disabledForeground = @disabledForeground
|
||||||
[Monokai_Pro---Mallowigi]Tree.selectionForeground = lazy(Table.selectionForeground)
|
{Material_Deep_Ocean}*.inactiveForeground = @disabledForeground
|
||||||
[Monokai_Pro---Mallowigi]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
{Material_Deep_Ocean}*.selectionBackground = lighten($ColorPalette.tree,15%)
|
||||||
[Monokai_Pro---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
{Material_Deep_Ocean}ProgressBar.selectionBackground = #fff
|
||||||
[Monokai_Pro---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Material_Deep_Ocean}Slider.trackColor = lighten(#1A1C25,5%)
|
||||||
|
{Material_Deep_Ocean}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
[Moonlight]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
{Material_Lighter}@disabledForeground = shade($ColorPalette.dis,30%)
|
||||||
[Moonlight]Table.selectionBackground = lazy(List.selectionBackground)
|
{Material_Lighter}*.disabledText = @disabledForeground
|
||||||
[Moonlight]Separator.foreground = lazy(Slider.trackColor)
|
{Material_Lighter}*.disabledForeground = @disabledForeground
|
||||||
[Moonlight]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Material_Lighter}*.inactiveForeground = @disabledForeground
|
||||||
|
{Material_Lighter}ComboBox.selectionBackground = $List.selectionBackground
|
||||||
|
{Material_Lighter}List.selectionForeground = $Table.selectionForeground
|
||||||
|
{Material_Lighter}List.selectionInactiveForeground = $Table.selectionInactiveForeground
|
||||||
|
{Material_Lighter}ProgressBar.selectionBackground = #222
|
||||||
|
{Material_Lighter}RadioButtonMenuItem.selectionForeground = $Table.selectionForeground
|
||||||
|
{Material_Lighter}Table.selectionBackground = $List.selectionBackground
|
||||||
|
{Material_Lighter}Tree.selectionForeground = $Table.selectionForeground
|
||||||
|
{Material_Lighter}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
[Night_Owl]ProgressBar.selectionBackground = #ddd
|
{Material_Oceanic}@disabledForeground = tint($ColorPalette.dis,30%)
|
||||||
[Night_Owl]ProgressBar.selectionForeground = #ddd
|
{Material_Oceanic}*.disabledText = @disabledForeground
|
||||||
|
{Material_Oceanic}*.disabledForeground = @disabledForeground
|
||||||
|
{Material_Oceanic}*.inactiveForeground = @disabledForeground
|
||||||
|
{Material_Oceanic}ProgressBar.selectionBackground = #ddd
|
||||||
|
{Material_Oceanic}ProgressBar.selectionForeground = #ddd
|
||||||
|
{Material_Oceanic}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{Material_Oceanic}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Material_Oceanic}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Material_Oceanic}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Solarized_Dark---Mallowigi]ProgressBar.selectionBackground = #ccc
|
{Material_Palenight}@disabledForeground = tint($ColorPalette.dis,20%)
|
||||||
[Solarized_Dark---Mallowigi]ProgressBar.selectionForeground = #ccc
|
{Material_Palenight}*.disabledText = @disabledForeground
|
||||||
[Solarized_Dark---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
{Material_Palenight}*.disabledForeground = @disabledForeground
|
||||||
[Solarized_Dark---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Material_Palenight}*.inactiveForeground = @disabledForeground
|
||||||
|
{Material_Palenight}ProgressBar.selectionBackground = #ddd
|
||||||
|
{Material_Palenight}ProgressBar.selectionForeground = #ddd
|
||||||
|
{Material_Palenight}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{Material_Palenight}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Material_Palenight}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Material_Palenight}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
[Solarized_Light---Mallowigi]ProgressBar.selectionBackground = #222
|
{Monokai_Pro---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%)
|
||||||
[Solarized_Light---Mallowigi]ProgressBar.selectionForeground = #fff
|
{Monokai_Pro---Mallowigi}*.disabledText = @disabledForeground
|
||||||
[Solarized_Light---Mallowigi]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
{Monokai_Pro---Mallowigi}*.disabledForeground = @disabledForeground
|
||||||
[Solarized_Light---Mallowigi]Table.selectionBackground = lazy(List.selectionBackground)
|
{Monokai_Pro---Mallowigi}*.inactiveForeground = @disabledForeground
|
||||||
[Solarized_Light---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
{Monokai_Pro---Mallowigi}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
|
||||||
[Solarized_Light---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
{Monokai_Pro---Mallowigi}List.selectionForeground = $Table.selectionForeground
|
||||||
|
{Monokai_Pro---Mallowigi}Tree.selectionForeground = $Table.selectionForeground
|
||||||
|
{Monokai_Pro---Mallowigi}List.selectionInactiveForeground = $Table.selectionInactiveForeground
|
||||||
|
{Monokai_Pro---Mallowigi}List.selectionBackground = $Table.selectionBackground
|
||||||
|
{Monokai_Pro---Mallowigi}Tree.selectionBackground = $Table.selectionBackground
|
||||||
|
{Monokai_Pro---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
{Monokai_Pro---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||||
|
|
||||||
|
{Moonlight}ComboBox.selectionBackground = $List.selectionBackground
|
||||||
|
{Moonlight}ProgressBar.selectionForeground = #000
|
||||||
|
{Moonlight}Table.selectionBackground = $List.selectionBackground
|
||||||
|
{Moonlight}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
|
{Solarized_Dark---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%)
|
||||||
|
{Solarized_Dark---Mallowigi}*.disabledForeground = @disabledForeground
|
||||||
|
{Solarized_Dark---Mallowigi}*.inactiveForeground = @disabledForeground
|
||||||
|
{Solarized_Dark---Mallowigi}*.disabledText = @disabledForeground
|
||||||
|
{Solarized_Dark---Mallowigi}ProgressBar.selectionBackground = #ccc
|
||||||
|
{Solarized_Dark---Mallowigi}ProgressBar.selectionForeground = #ccc
|
||||||
|
{Solarized_Dark---Mallowigi}Slider.trackColor = lighten(@background,10%)
|
||||||
|
{Solarized_Dark---Mallowigi}Table.selectionBackground = $List.selectionBackground
|
||||||
|
{Solarized_Dark---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
|
||||||
|
{Solarized_Light---Mallowigi}@disabledForeground = tint(@foreground,30%)
|
||||||
|
{Solarized_Light---Mallowigi}*.disabledForeground = @disabledForeground
|
||||||
|
{Solarized_Light---Mallowigi}*.inactiveForeground = @disabledForeground
|
||||||
|
{Solarized_Light---Mallowigi}*.disabledText = @disabledForeground
|
||||||
|
{Solarized_Light---Mallowigi}ProgressBar.selectionBackground = #222
|
||||||
|
{Solarized_Light---Mallowigi}ComboBox.selectionBackground = $List.selectionBackground
|
||||||
|
{Solarized_Light---Mallowigi}Slider.disabledTrackColor = lighten($Slider.trackColor,5%)
|
||||||
|
{Solarized_Light---Mallowigi}Table.selectionBackground = $List.selectionBackground
|
||||||
|
{Solarized_Light---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||||
|
{Solarized_Light---Mallowigi}Button.toolbar.selectedBackground = darken($@background,15%)
|
||||||
|
{Solarized_Light---Mallowigi}ToggleButton.toolbar.selectedBackground = $Button.toolbar.selectedBackground
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -112,6 +112,7 @@ Button.borderWidth = 0
|
|||||||
Button.disabledBackground = darken($Button.background,10%)
|
Button.disabledBackground = darken($Button.background,10%)
|
||||||
|
|
||||||
Button.default.borderWidth = 0
|
Button.default.borderWidth = 0
|
||||||
|
Button.default.foreground = contrast($Button.default.background, @background, @selectionForeground, 25%)
|
||||||
|
|
||||||
Button.toolbar.hoverBackground = #fff1
|
Button.toolbar.hoverBackground = #fff1
|
||||||
Button.toolbar.pressedBackground = #fff2
|
Button.toolbar.pressedBackground = #fff2
|
||||||
@@ -183,6 +184,7 @@ MenuBar.selectionEmbeddedInsets = 3,0,3,0
|
|||||||
MenuBar.selectionArc = 8
|
MenuBar.selectionArc = 8
|
||||||
MenuBar.selectionBackground = lighten(@menuBackground,15%,derived)
|
MenuBar.selectionBackground = lighten(@menuBackground,15%,derived)
|
||||||
MenuBar.selectionForeground = @foreground
|
MenuBar.selectionForeground = @foreground
|
||||||
|
MenuBar.borderColor = over($Separator.foreground,$MenuBar.background)
|
||||||
|
|
||||||
|
|
||||||
#---- MenuItem ----
|
#---- MenuItem ----
|
||||||
@@ -293,6 +295,7 @@ TextPane.selectionForeground = @textSelectionForeground
|
|||||||
|
|
||||||
ToggleButton.disabledBackground = $Button.disabledBackground
|
ToggleButton.disabledBackground = $Button.disabledBackground
|
||||||
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
||||||
|
ToggleButton.selectedForeground = lighten($ToggleButton.foreground,20%)
|
||||||
|
|
||||||
ToggleButton.toolbar.selectedBackground = #fff3
|
ToggleButton.toolbar.selectedBackground = #fff3
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
# general background and foreground (text color)
|
# general background and foreground (text color)
|
||||||
@background = #f6f6f6
|
@background = #f6f6f6
|
||||||
@foreground = over(@nsControlTextColor,@background)
|
@foreground = over(@nsControlTextColor,@background)
|
||||||
@disabledForeground = over(@nsTertiaryLabelColor,@background)
|
@disabledForeground = over(@nsSecondaryLabelColor,@background)
|
||||||
|
|
||||||
# component background
|
# component background
|
||||||
@buttonBackground = @nsControlColor
|
@buttonBackground = @nsControlColor
|
||||||
@@ -184,6 +184,7 @@ MenuBar.selectionEmbeddedInsets = 3,0,3,0
|
|||||||
MenuBar.selectionArc = 8
|
MenuBar.selectionArc = 8
|
||||||
MenuBar.selectionBackground = darken(@menuBackground,15%,derived)
|
MenuBar.selectionBackground = darken(@menuBackground,15%,derived)
|
||||||
MenuBar.selectionForeground = @foreground
|
MenuBar.selectionForeground = @foreground
|
||||||
|
MenuBar.borderColor = over($Separator.foreground,$MenuBar.background)
|
||||||
|
|
||||||
|
|
||||||
#---- MenuItem ----
|
#---- MenuItem ----
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
@@ -27,8 +30,16 @@ import javax.swing.border.Border;
|
|||||||
import javax.swing.UIDefaults.ActiveValue;
|
import javax.swing.UIDefaults.ActiveValue;
|
||||||
import javax.swing.UIDefaults.LazyValue;
|
import javax.swing.UIDefaults.LazyValue;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.function.Executable;
|
||||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||||
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.Fade;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.HSLChange;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.HSLIncreaseDecrease;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.Mix;
|
||||||
|
import com.formdev.flatlaf.util.ColorFunctions.Mix2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -84,10 +95,12 @@ public class TestUIDefaultsLoader
|
|||||||
void parseBorders() {
|
void parseBorders() {
|
||||||
Insets insets = new Insets( 1,2,3,4 );
|
Insets insets = new Insets( 1,2,3,4 );
|
||||||
assertBorderEquals( new FlatEmptyBorder( insets ), "1,2,3,4" );
|
assertBorderEquals( new FlatEmptyBorder( insets ), "1,2,3,4" );
|
||||||
|
assertBorderEquals( new FlatEmptyBorder( insets ), "1,2,3,4,,," );
|
||||||
assertBorderEquals( new FlatLineBorder( insets, Color.red ), "1,2,3,4,#f00" );
|
assertBorderEquals( new FlatLineBorder( insets, Color.red ), "1,2,3,4,#f00" );
|
||||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 0 ), "1,2,3,4,#f00,2.5" );
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, -1 ), "1,2,3,4,#f00,2.5" );
|
||||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 6 ), "1,2,3,4,#f00,2.5,6" );
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 6 ), "1,2,3,4,#f00,2.5,6" );
|
||||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 1, 6 ), "1,2,3,4,#f00,,6" );
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 1, 6 ), "1,2,3,4,#f00,,6" );
|
||||||
|
assertBorderEquals( new FlatLineBorder( insets, null, 1, 6 ), "1,2,3,4,,,6" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertBorderEquals( Border expected, String actualStyle ) {
|
private void assertBorderEquals( Border expected, String actualStyle ) {
|
||||||
@@ -178,6 +191,336 @@ public class TestUIDefaultsLoader
|
|||||||
assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) );
|
assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseColorFunctions() {
|
||||||
|
// lighten
|
||||||
|
assertEquals( new Color( 0xff6666 ), parseColor( "lighten(#f00, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0xff3333 ), parseColor( "lighten(#f00, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0xaaaaaa ), parseColor( "lighten(#ddd, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0xb1b1b1 ), parseColor( "lighten(#ddd, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// darken
|
||||||
|
assertEquals( new Color( 0x990000 ), parseColor( "darken(#f00, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0xcc0000 ), parseColor( "darken(#f00, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0x555555 ), parseColor( "darken(#222, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0x292929 ), parseColor( "darken(#222, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// saturate
|
||||||
|
assertEquals( new Color( 0xf32e2e ), parseColor( "saturate(#d44, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0xec3535 ), parseColor( "saturate(#d44, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0xc75a5a ), parseColor( "saturate(#d44, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0xce5353 ), parseColor( "saturate(#d44, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// desaturate
|
||||||
|
assertEquals( new Color( 0x745858 ), parseColor( "desaturate(#844, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0x814b4b ), parseColor( "desaturate(#844, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0x9c3030 ), parseColor( "desaturate(#844, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0x8f3d3d ), parseColor( "desaturate(#844, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// fadein
|
||||||
|
assertEquals( new Color( 0xddff0000, true ), parseColor( "fadein(#f00a, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0xccff0000, true ), parseColor( "fadein(#f00a, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadein(#f00a, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0x88ff0000, true ), parseColor( "fadein(#f00a, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// fadeout
|
||||||
|
assertEquals( new Color( 0x11ff0000, true ), parseColor( "fadeout(#f004, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0x36ff0000, true ), parseColor( "fadeout(#f004, 20%, relative)" ) );
|
||||||
|
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadeout(#f004, 20%, autoInverse)" ) );
|
||||||
|
assertEquals( new Color( 0x52ff0000, true ), parseColor( "fadeout(#f004, 20%, relative autoInverse)" ) );
|
||||||
|
|
||||||
|
// fade
|
||||||
|
assertEquals( new Color( 0x33ff0000, true ), parseColor( "fade(#f00, 20%)" ) );
|
||||||
|
assertEquals( new Color( 0xccff0000, true ), parseColor( "fade(#ff000010, 80%)" ) );
|
||||||
|
|
||||||
|
// spin
|
||||||
|
assertEquals( new Color( 0xffaa00 ), parseColor( "spin(#f00, 40)" ) );
|
||||||
|
assertEquals( new Color( 0xff00aa ), parseColor( "spin(#f00, -40)" ) );
|
||||||
|
|
||||||
|
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||||
|
assertEquals( new Color( 0xffaa00 ), parseColor( "changeHue(#f00, 40)" ) );
|
||||||
|
assertEquals( new Color( 0xb34d4d ), parseColor( "changeSaturation(#f00, 40%)" ) );
|
||||||
|
assertEquals( new Color( 0xcc0000 ), parseColor( "changeLightness(#f00, 40%)" ) );
|
||||||
|
assertEquals( new Color( 0x66ff0000, true ), parseColor( "changeAlpha(#f00, 40%)" ) );
|
||||||
|
|
||||||
|
// mix
|
||||||
|
assertEquals( new Color( 0x808000 ), parseColor( "mix(#f00, #0f0)" ) );
|
||||||
|
assertEquals( new Color( 0xbf4000 ), parseColor( "mix(#f00, #0f0, 75%)" ) );
|
||||||
|
|
||||||
|
// tint
|
||||||
|
assertEquals( new Color( 0xff80ff ), parseColor( "tint(#f0f)" ) );
|
||||||
|
assertEquals( new Color( 0xffbfff ), parseColor( "tint(#f0f, 75%)" ) );
|
||||||
|
|
||||||
|
// shade
|
||||||
|
assertEquals( new Color( 0x800080 ), parseColor( "shade(#f0f)" ) );
|
||||||
|
assertEquals( new Color( 0x400040 ), parseColor( "shade(#f0f, 75%)" ) );
|
||||||
|
|
||||||
|
// contrast
|
||||||
|
assertEquals( new Color( 0x0000ff ), parseColor( "contrast(#bbb, #00f, #0f0)" ) );
|
||||||
|
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#444, #00f, #0f0)" ) );
|
||||||
|
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#bbb, #00f, #0f0, 60%)" ) );
|
||||||
|
|
||||||
|
// rgb / rgba
|
||||||
|
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
|
||||||
|
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
|
||||||
|
assertEquals( new Color( 0x197fb2 ), parseColor( "rgb(10%,50%,70%)" ) );
|
||||||
|
assertEquals( new Color( 0x197f46 ), parseColor( "rgb(10%,50%,70)" ) );
|
||||||
|
assertEquals( new Color( 0x405a8120, true ), parseColor( "rgba(90, 129, 32, 64)" ) );
|
||||||
|
assertEquals( new Color( 0x335a8120, true ), parseColor( "rgba(90, 129, 32, 20%)" ) );
|
||||||
|
|
||||||
|
// hsl / hsla
|
||||||
|
assertEquals( new Color( 0x7fff00 ), parseColor( "hsl(90, 100%, 50%)" ) );
|
||||||
|
assertEquals( new Color( 0x337fff00, true ), parseColor( "hsla(90, 100%, 50%, 20%)" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseLazyColorFunctions() {
|
||||||
|
// lighten
|
||||||
|
assertEquals( new Color( 0xff6666 ), parseColorLazy( "lighten(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
|
||||||
|
// darken
|
||||||
|
assertEquals( new Color( 0x990000 ), parseColorLazy( "darken(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
|
||||||
|
// saturate
|
||||||
|
assertEquals( new Color( 0xf32e2e ), parseColorLazy( "saturate(dummyColor, 20%, lazy)", new Color( 0xdd4444 ) ) );
|
||||||
|
|
||||||
|
// desaturate
|
||||||
|
assertEquals( new Color( 0x745858 ), parseColorLazy( "desaturate(dummyColor, 20%, lazy)", new Color( 0x884444 ) ) );
|
||||||
|
|
||||||
|
// fadein
|
||||||
|
assertEquals( new Color( 0xddff0000, true ), parseColorLazy( "fadein(dummyColor, 20%, lazy)", new Color( 0xaaff0000, true ) ) );
|
||||||
|
|
||||||
|
// fadeout
|
||||||
|
assertEquals( new Color( 0x11ff0000, true ), parseColorLazy( "fadeout(dummyColor, 20%, lazy)", new Color( 0x44ff0000, true ) ) );
|
||||||
|
|
||||||
|
// fade
|
||||||
|
assertEquals( new Color( 0x33ff0000, true ), parseColorLazy( "fade(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
assertEquals( new Color( 0xccff0000, true ), parseColorLazy( "fade(dummyColor, 80%, lazy)", new Color( 0x10ff0000, true ) ) );
|
||||||
|
|
||||||
|
// spin
|
||||||
|
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "spin(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
assertEquals( new Color( 0xff00aa ), parseColorLazy( "spin(dummyColor, -40, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
|
||||||
|
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||||
|
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "changeHue(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
assertEquals( new Color( 0xb34d4d ), parseColorLazy( "changeSaturation(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
assertEquals( new Color( 0xcc0000 ), parseColorLazy( "changeLightness(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
assertEquals( new Color( 0x66ff0000, true ), parseColorLazy( "changeAlpha(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||||
|
|
||||||
|
// mix
|
||||||
|
assertEquals( new Color( 0x808000 ), parseColorLazy( "mix(#f00, dummyColor, lazy)", new Color( 0x00ff00 ) ) );
|
||||||
|
assertEquals( new Color( 0xbf4000 ), parseColorLazy( "mix(#f00, dummyColor, 75%, lazy)", new Color( 0x00ff00 ) ) );
|
||||||
|
|
||||||
|
// tint
|
||||||
|
assertEquals( new Color( 0xff80ff ), parseColorLazy( "tint(dummyColor, lazy)", new Color( 0xff00ff ) ) );
|
||||||
|
assertEquals( new Color( 0xffbfff ), parseColorLazy( "tint(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
|
||||||
|
|
||||||
|
// shade
|
||||||
|
assertEquals( new Color( 0x800080 ), parseColorLazy( "shade(dummyColor, lazy)", new Color( 0xff00ff ) ) );
|
||||||
|
assertEquals( new Color( 0x400040 ), parseColorLazy( "shade(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseDerivedColorFunctions() {
|
||||||
|
// mix
|
||||||
|
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( Color.red, 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( Color.red, 75 ) );
|
||||||
|
|
||||||
|
// tint
|
||||||
|
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( Color.white, 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( Color.white, 75 ) );
|
||||||
|
|
||||||
|
// shade
|
||||||
|
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( Color.black, 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( Color.black, 75 ) );
|
||||||
|
|
||||||
|
|
||||||
|
// lighten
|
||||||
|
assertDerivedColorEquals( new Color( 0xff6666 ), "lighten(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, true, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xff3333 ), "lighten(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, true, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, true, false ) );
|
||||||
|
|
||||||
|
// darken
|
||||||
|
assertDerivedColorEquals( new Color( 0x990000 ), "darken(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, false, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xcc0000 ), "darken(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, false, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x000000 ), "darken(#222, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x1b1b1b ), "darken(#222, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, true, false ) );
|
||||||
|
|
||||||
|
// saturate
|
||||||
|
assertDerivedColorEquals( new Color( 0xc75a5a ), "saturate(#d44, 20%, derived)", new HSLIncreaseDecrease( 1, true, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xce5353 ), "saturate(#d44, 20%, derived relative)", new HSLIncreaseDecrease( 1, true, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xf32e2e ), "saturate(#d44, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xec3535 ), "saturate(#d44, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, true, false ) );
|
||||||
|
|
||||||
|
// desaturate
|
||||||
|
assertDerivedColorEquals( new Color( 0x9c3030 ), "desaturate(#844, 20%, derived)", new HSLIncreaseDecrease( 1, false, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x8f3d3d ), "desaturate(#844, 20%, derived relative)", new HSLIncreaseDecrease( 1, false, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x745858 ), "desaturate(#844, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x814b4b ), "desaturate(#844, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, true, false ) );
|
||||||
|
|
||||||
|
// fadein
|
||||||
|
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadein(#f00a, 20%, derived)", new HSLIncreaseDecrease( 3, true, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x88ff0000, true ), "fadein(#f00a, 20%, derived relative)", new HSLIncreaseDecrease( 3, true, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xddff0000, true ), "fadein(#f00a, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fadein(#f00a, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, true, false ) );
|
||||||
|
|
||||||
|
// fadeout
|
||||||
|
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadeout(#f004, 20%, derived)", new HSLIncreaseDecrease( 3, false, 20, false, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x52ff0000, true ), "fadeout(#f004, 20%, derived relative)", new HSLIncreaseDecrease( 3, false, 20, true, true ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x11ff0000, true ), "fadeout(#f004, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x36ff0000, true ), "fadeout(#f004, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, true, false ) );
|
||||||
|
|
||||||
|
// fade
|
||||||
|
assertDerivedColorEquals( new Color( 0x33ff0000, true ), "fade(#f00, 20%, derived)", new Fade( 20 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fade(#ff000010, 80%, derived)", new Fade( 80 ) );
|
||||||
|
|
||||||
|
// spin
|
||||||
|
assertDerivedColorEquals( new Color( 0xffaa00 ), "spin(#f00, 40, derived)", new HSLIncreaseDecrease( 0, true, 40, false, false ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xff00aa ), "spin(#f00, -40, derived)", new HSLIncreaseDecrease( 0, true, -40, false, false ) );
|
||||||
|
|
||||||
|
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||||
|
assertDerivedColorEquals( new Color( 0xffaa00 ), "changeHue(#f00, 40, derived)", new HSLChange( 0, 40 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xb34d4d ), "changeSaturation(#f00, 40%, derived)", new HSLChange( 1, 40 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xcc0000 ), "changeLightness(#f00, 40%, derived)", new HSLChange( 2, 40 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x66ff0000, true ), "changeAlpha(#f00, 40%, derived)", new HSLChange( 3, 40 ) );
|
||||||
|
|
||||||
|
// mix
|
||||||
|
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( new Color( 0xff0000 ), 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( new Color( 0xff0000 ), 75 ) );
|
||||||
|
|
||||||
|
// tint
|
||||||
|
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( new Color( 0xffffff ), 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( new Color( 0xffffff ), 75 ) );
|
||||||
|
|
||||||
|
// shade
|
||||||
|
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( new Color( 0x000000 ), 50 ) );
|
||||||
|
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( new Color( 0x000000 ), 75 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertDerivedColorEquals( Color expectedColor, String actualStyle, ColorFunction... expectedFunctions ) {
|
||||||
|
Object actual = parseColor( actualStyle );
|
||||||
|
assertInstanceOf( DerivedColor.class, actual );
|
||||||
|
assertEquals( expectedColor, actual );
|
||||||
|
|
||||||
|
ColorFunction[] actualFunctions = ((DerivedColor)actual).getFunctions();
|
||||||
|
assertEquals( expectedFunctions.length, actualFunctions.length );
|
||||||
|
for( int i = 0; i < expectedFunctions.length; i++ )
|
||||||
|
assertColorFunctionEquals( expectedFunctions[i], actualFunctions[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertColorFunctionEquals( ColorFunction expected, ColorFunction actual ) {
|
||||||
|
assertEquals( expected.getClass(), actual.getClass() );
|
||||||
|
|
||||||
|
if( expected instanceof HSLIncreaseDecrease ) {
|
||||||
|
HSLIncreaseDecrease e = (HSLIncreaseDecrease) expected;
|
||||||
|
HSLIncreaseDecrease a = (HSLIncreaseDecrease) actual;
|
||||||
|
assertEquals( e.hslIndex, a.hslIndex );
|
||||||
|
assertEquals( e.increase, a.increase );
|
||||||
|
assertEquals( e.amount, a.amount );
|
||||||
|
assertEquals( e.relative, a.relative );
|
||||||
|
assertEquals( e.autoInverse, a.autoInverse );
|
||||||
|
} else if( expected instanceof HSLChange ) {
|
||||||
|
HSLChange e = (HSLChange) expected;
|
||||||
|
HSLChange a = (HSLChange) actual;
|
||||||
|
assertEquals( e.hslIndex, a.hslIndex );
|
||||||
|
assertEquals( e.value, a.value );
|
||||||
|
} else if( expected instanceof Fade ) {
|
||||||
|
Fade e = (Fade) expected;
|
||||||
|
Fade a = (Fade) actual;
|
||||||
|
assertEquals( e.amount, a.amount );
|
||||||
|
} else if( expected instanceof Mix ) {
|
||||||
|
Mix e = (Mix) expected;
|
||||||
|
Mix a = (Mix) actual;
|
||||||
|
assertEquals( e.color2, a.color2 );
|
||||||
|
assertEquals( e.weight, a.weight );
|
||||||
|
} else if( expected instanceof Mix2 ) {
|
||||||
|
Mix2 e = (Mix2) expected;
|
||||||
|
Mix2 a = (Mix2) actual;
|
||||||
|
assertEquals( e.color1, a.color1 );
|
||||||
|
assertEquals( e.weight, a.weight );
|
||||||
|
} else
|
||||||
|
assertTrue( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseColor( String value ) {
|
||||||
|
return UIDefaultsLoader.parseValue( "dummyColor", value, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object parseColorLazy( String value, Color actual ) {
|
||||||
|
UIManager.put( "dummyColor", actual );
|
||||||
|
Object v = UIDefaultsLoader.parseValue( "dummyColor", value, null );
|
||||||
|
assertInstanceOf( LazyValue.class, v );
|
||||||
|
return ((LazyValue)v).createValue( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- invalid values -----------------------------------------------------
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseInvalidValue() {
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", null ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid integer or float '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", null ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid integer or float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", null ) );
|
||||||
|
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid insets '1,abc,3,4'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,abc,3,4", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid insets '1,2,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid size '1abc'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid size '1'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummy", "#f0", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummyColor", "#f0", null ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseInvalidValueWithJavaType() {
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid boolean 'falseyy'" ), () -> UIDefaultsLoader.parseValue( "dummy", "falseyy", boolean.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid boolean 'falseyy'" ), () -> UIDefaultsLoader.parseValue( "dummy", "falseyy", Boolean.class ) );
|
||||||
|
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", char.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", Character.class ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid integer '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", int.class ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid integer '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", Integer.class ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", float.class ) );
|
||||||
|
assertThrows( new NumberFormatException( "invalid float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", Float.class ) );
|
||||||
|
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid insets '1,abc,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,abc,3", Insets.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid insets '1,2,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3", Insets.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid size '1abc'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1abc", Dimension.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid size '1'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1", Dimension.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummy", "#f0", Color.class ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummyColor", "#f0", Color.class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseInvalidBorders() {
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,abc,3,4' (invalid insets '1,abc,3,4')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,abc,3,4", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,2,3' (invalid insets '1,2,3')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,,,' (invalid insets '1,2,3,,,')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,,,", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f0' (invalid color '#f0')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f0", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f00,2.5abc' (invalid float '2.5abc')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f00,2.5abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f00,2.5,6abc' (invalid integer '6abc')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f00,2.5,6abc", null ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseInvalidFonts() {
|
||||||
|
// size
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '12abc' (invalid integer '12abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "12abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '+12abc' (invalid integer '+12abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+12abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '+3abc' (invalid integer '+3abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+3abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '-4abc' (invalid integer '-4abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "-4abc", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '150abc%' (invalid integer '150abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "150abc%", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font 'bold 13abc Monospaced' (invalid integer '13abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "bold 13abc Monospaced", null ) );
|
||||||
|
|
||||||
|
// invalid combinations of styles
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font 'bold +italic': can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "bold +italic", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '+bold -bold': can not use '+bold' and '-bold'" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+bold -bold", null ) );
|
||||||
|
assertThrows( new IllegalArgumentException( "invalid font '+italic -italic': can not use '+italic' and '-italic'" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+italic -italic", null ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThrows( Throwable expected, Executable executable ) {
|
||||||
|
Throwable actual = assertThrowsExactly( expected.getClass(), executable );
|
||||||
|
assertEquals( expected.getMessage(), actual.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class TestInstance -------------------------------------------------
|
//---- class TestInstance -------------------------------------------------
|
||||||
|
|
||||||
@SuppressWarnings( "EqualsHashCode" ) // Error Prone
|
@SuppressWarnings( "EqualsHashCode" ) // Error Prone
|
||||||
|
|||||||
@@ -0,0 +1,404 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JRootPane;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class TestFlatButton
|
||||||
|
{
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() {
|
||||||
|
String[] defs = {
|
||||||
|
"Button.background", "#000001",
|
||||||
|
"Button.foreground", "#000002",
|
||||||
|
"Button.focusedBackground", "#000003",
|
||||||
|
"Button.focusedForeground", "#000004",
|
||||||
|
"Button.hoverBackground", "#000005",
|
||||||
|
"Button.hoverForeground", "#000006",
|
||||||
|
"Button.pressedBackground", "#000007",
|
||||||
|
"Button.pressedForeground", "#000008",
|
||||||
|
"Button.selectedBackground", "#000009",
|
||||||
|
"Button.selectedForeground", "#00000a",
|
||||||
|
"Button.disabledBackground", "#00000b",
|
||||||
|
"Button.disabledText", "#00000c",
|
||||||
|
"Button.disabledSelectedBackground", "#00000d",
|
||||||
|
"Button.disabledSelectedForeground", "#00000e",
|
||||||
|
|
||||||
|
"Button.default.background", "#000101",
|
||||||
|
"Button.default.foreground", "#000102",
|
||||||
|
"Button.default.focusedBackground", "#000103",
|
||||||
|
"Button.default.focusedForeground", "#000104",
|
||||||
|
"Button.default.hoverBackground", "#000105",
|
||||||
|
"Button.default.hoverForeground", "#000106",
|
||||||
|
"Button.default.pressedBackground", "#000107",
|
||||||
|
"Button.default.pressedForeground", "#000108",
|
||||||
|
|
||||||
|
"Button.toolbar.hoverBackground", "#000201",
|
||||||
|
"Button.toolbar.hoverForeground", "#000202",
|
||||||
|
"Button.toolbar.pressedBackground", "#000203",
|
||||||
|
"Button.toolbar.pressedForeground", "#000204",
|
||||||
|
"Button.toolbar.selectedBackground", "#000205",
|
||||||
|
"Button.toolbar.selectedForeground", "#000206",
|
||||||
|
"Button.toolbar.disabledSelectedBackground", "#000207",
|
||||||
|
"Button.toolbar.disabledSelectedForeground", "#000208",
|
||||||
|
};
|
||||||
|
|
||||||
|
HashMap<String, String> globalExtraDefaults = new HashMap<>();
|
||||||
|
for( int i = 0; i < defs.length; i += 2 )
|
||||||
|
globalExtraDefaults.put( defs[i], defs[i+1] );
|
||||||
|
FlatLaf.setGlobalExtraDefaults( globalExtraDefaults );
|
||||||
|
|
||||||
|
TestUtils.setup( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void cleanup() {
|
||||||
|
TestUtils.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void background() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
UIManager.getColor( "Button.background" ),
|
||||||
|
UIManager.getColor( "Button.disabledBackground" ),
|
||||||
|
UIManager.getColor( "Button.focusedBackground" ),
|
||||||
|
UIManager.getColor( "Button.hoverBackground" ),
|
||||||
|
UIManager.getColor( "Button.pressedBackground" ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
UIManager.getColor( "Button.selectedBackground" ),
|
||||||
|
UIManager.getColor( "Button.disabledSelectedBackground" ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.pressedBackground" ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
UIManager.getColor( "Button.default.background" ),
|
||||||
|
UIManager.getColor( "Button.disabledBackground" ),
|
||||||
|
UIManager.getColor( "Button.default.focusedBackground" ),
|
||||||
|
UIManager.getColor( "Button.default.hoverBackground" ),
|
||||||
|
UIManager.getColor( "Button.default.pressedBackground" ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void foreground() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
UIManager.getColor( "Button.foreground" ),
|
||||||
|
UIManager.getColor( "Button.disabledText" ),
|
||||||
|
UIManager.getColor( "Button.focusedForeground" ),
|
||||||
|
UIManager.getColor( "Button.hoverForeground" ),
|
||||||
|
UIManager.getColor( "Button.pressedForeground" ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
UIManager.getColor( "Button.selectedForeground" ),
|
||||||
|
FlatUIUtils.getUIColor( "Button.disabledSelectedForeground", "Button.disabledText" ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.pressedForeground" ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
UIManager.getColor( "Button.default.foreground" ),
|
||||||
|
UIManager.getColor( "Button.disabledText" ),
|
||||||
|
UIManager.getColor( "Button.default.focusedForeground" ),
|
||||||
|
UIManager.getColor( "Button.default.hoverForeground" ),
|
||||||
|
UIManager.getColor( "Button.default.pressedForeground" ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void backgroundExplicit() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
Color c = new Color( 0x020001 );
|
||||||
|
b.setBackground( c );
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
c,
|
||||||
|
UIManager.getColor( "Button.disabledBackground" ),
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.hoverBackground" ),
|
||||||
|
UIManager.getColor( "Button.pressedBackground" ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
UIManager.getColor( "Button.selectedBackground" ),
|
||||||
|
UIManager.getColor( "Button.disabledSelectedBackground" ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.pressedBackground" ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
c,
|
||||||
|
UIManager.getColor( "Button.disabledBackground" ),
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.default.hoverBackground" ),
|
||||||
|
UIManager.getColor( "Button.default.pressedBackground" ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void foregroundExplicit() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
Color c = new Color( 0x020001 );
|
||||||
|
b.setForeground( c );
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
c,
|
||||||
|
UIManager.getColor( "Button.disabledText" ),
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.hoverForeground" ),
|
||||||
|
UIManager.getColor( "Button.pressedForeground" ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
c,
|
||||||
|
FlatUIUtils.getUIColor( "Button.disabledSelectedForeground", "Button.disabledText" ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.pressedForeground" ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
c,
|
||||||
|
UIManager.getColor( "Button.disabledText" ),
|
||||||
|
null,
|
||||||
|
UIManager.getColor( "Button.default.hoverForeground" ),
|
||||||
|
UIManager.getColor( "Button.default.pressedForeground" ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void backgroundStyled() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
b.putClientProperty( FlatClientProperties.STYLE,
|
||||||
|
"background: #020001;" +
|
||||||
|
"disabledBackground: #020002;" +
|
||||||
|
"focusedBackground: #020003;" +
|
||||||
|
"hoverBackground: #020004;" +
|
||||||
|
"pressedBackground: #020005;" +
|
||||||
|
"selectedBackground: #020006;" +
|
||||||
|
"disabledSelectedBackground: #020007;" );
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
new Color( 0x020001 ),
|
||||||
|
new Color( 0x020002 ),
|
||||||
|
new Color( 0x020003 ),
|
||||||
|
new Color( 0x020004 ),
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
new Color( 0x020006 ),
|
||||||
|
new Color( 0x020007 ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
|
||||||
|
Color c = new Color( 0x0a0001 );
|
||||||
|
b.setBackground( c );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
c,
|
||||||
|
new Color( 0x020002 ),
|
||||||
|
c,
|
||||||
|
new Color( 0x020004 ),
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
new Color( 0x020006 ),
|
||||||
|
new Color( 0x020007 ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
|
||||||
|
b = new JButton();
|
||||||
|
b.putClientProperty( FlatClientProperties.STYLE,
|
||||||
|
"default.background: #020101;" +
|
||||||
|
"disabledBackground: #020102;" +
|
||||||
|
"default.focusedBackground: #020103;" +
|
||||||
|
"default.hoverBackground: #020104;" +
|
||||||
|
"default.pressedBackground: #020105;" );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
|
||||||
|
new Color( 0x020101 ),
|
||||||
|
new Color( 0x020102 ),
|
||||||
|
new Color( 0x020103 ),
|
||||||
|
new Color( 0x020104 ),
|
||||||
|
new Color( 0x020105 ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void foregroundStyled() {
|
||||||
|
JButton b = new JButton();
|
||||||
|
|
||||||
|
b.putClientProperty( FlatClientProperties.STYLE,
|
||||||
|
"foreground: #020001;" +
|
||||||
|
"disabledText: #020002;" +
|
||||||
|
"focusedForeground: #020003;" +
|
||||||
|
"hoverForeground: #020004;" +
|
||||||
|
"pressedForeground: #020005;" +
|
||||||
|
"selectedForeground: #020006;" +
|
||||||
|
"disabledSelectedForeground: #020007;" );
|
||||||
|
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
new Color( 0x020001 ),
|
||||||
|
new Color( 0x020002 ),
|
||||||
|
new Color( 0x020003 ),
|
||||||
|
new Color( 0x020004 ),
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
|
||||||
|
// selected
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
new Color( 0x020006 ),
|
||||||
|
new Color( 0x020007 ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
|
||||||
|
Color c = new Color( 0x0a0001 );
|
||||||
|
b.setForeground( c );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
c,
|
||||||
|
new Color( 0x020002 ),
|
||||||
|
c,
|
||||||
|
new Color( 0x020004 ),
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( true );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
c,
|
||||||
|
new Color( 0x020007 ),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new Color( 0x020005 ) );
|
||||||
|
b.setSelected( false );
|
||||||
|
|
||||||
|
|
||||||
|
b = new JButton();
|
||||||
|
b.putClientProperty( FlatClientProperties.STYLE,
|
||||||
|
"default.foreground: #020101;" +
|
||||||
|
"disabledText: #020102;" +
|
||||||
|
"default.focusedForeground: #020103;" +
|
||||||
|
"default.hoverForeground: #020104;" +
|
||||||
|
"default.pressedForeground: #020105;" );
|
||||||
|
|
||||||
|
// default
|
||||||
|
JRootPane rootPane = new JRootPane();
|
||||||
|
rootPane.getContentPane().add( b );
|
||||||
|
rootPane.setDefaultButton( b );
|
||||||
|
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
|
||||||
|
new Color( 0x020101 ),
|
||||||
|
new Color( 0x020102 ),
|
||||||
|
new Color( 0x020103 ),
|
||||||
|
new Color( 0x020104 ),
|
||||||
|
new Color( 0x020105 ) );
|
||||||
|
rootPane.getContentPane().remove( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testButtonColors( JButton b, Function<JButton, Color> f,
|
||||||
|
Color expectedEnabled, Color expectedDisabled, Color expectedFocused,
|
||||||
|
Color expectedHover, Color expectedPressed
|
||||||
|
)
|
||||||
|
{
|
||||||
|
assertEquals( expectedEnabled, f.apply( b ) );
|
||||||
|
|
||||||
|
// disabled
|
||||||
|
b.setEnabled( false );
|
||||||
|
assertEquals( expectedDisabled, f.apply( b ) );
|
||||||
|
b.setEnabled( true );
|
||||||
|
|
||||||
|
// focused
|
||||||
|
if( expectedFocused != null ) {
|
||||||
|
b.putClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER, (Predicate<JComponent>) c -> true );
|
||||||
|
assertEquals( expectedFocused, f.apply( b ) );
|
||||||
|
b.putClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
// hover
|
||||||
|
if( expectedHover != null ) {
|
||||||
|
b.getModel().setRollover( true );
|
||||||
|
assertEquals( expectedHover, f.apply( b ) );
|
||||||
|
b.getModel().setRollover( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
// pressed
|
||||||
|
if( expectedPressed != null ) {
|
||||||
|
b.getModel().setPressed( true );
|
||||||
|
assertEquals( expectedPressed, f.apply( b ) );
|
||||||
|
b.getModel().setPressed( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -253,7 +253,8 @@ public class TestFlatStyleableInfo
|
|||||||
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
"disabledForeground", Color.class
|
"disabledForeground", Color.class,
|
||||||
|
"arc", int.class
|
||||||
);
|
);
|
||||||
|
|
||||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||||
@@ -269,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,
|
||||||
|
|
||||||
@@ -516,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
|
||||||
@@ -524,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,
|
||||||
@@ -531,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,
|
||||||
@@ -538,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,
|
||||||
@@ -545,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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,6 +818,8 @@ public class TestFlatStyleableInfo
|
|||||||
"selectionForeground", Color.class,
|
"selectionForeground", Color.class,
|
||||||
"selectionInactiveBackground", Color.class,
|
"selectionInactiveBackground", Color.class,
|
||||||
"selectionInactiveForeground", Color.class,
|
"selectionInactiveForeground", Color.class,
|
||||||
|
"selectionInsets", Insets.class,
|
||||||
|
"selectionArc", int.class,
|
||||||
|
|
||||||
// FlatTableCellBorder
|
// FlatTableCellBorder
|
||||||
"cellMargins", Insets.class,
|
"cellMargins", Insets.class,
|
||||||
@@ -962,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,
|
||||||
@@ -993,12 +1016,20 @@ public class TestFlatStyleableInfo
|
|||||||
"disabledBorderColor", Color.class,
|
"disabledBorderColor", Color.class,
|
||||||
"focusedBorderColor", Color.class,
|
"focusedBorderColor", Color.class,
|
||||||
"hoverBorderColor", Color.class,
|
"hoverBorderColor", Color.class,
|
||||||
|
"pressedBorderColor", Color.class,
|
||||||
|
|
||||||
|
"selectedBorderColor", Color.class,
|
||||||
|
"disabledSelectedBorderColor", Color.class,
|
||||||
|
"focusedSelectedBorderColor", Color.class,
|
||||||
|
"hoverSelectedBorderColor", Color.class,
|
||||||
|
"pressedSelectedBorderColor", Color.class,
|
||||||
|
|
||||||
"default.borderWidth", float.class,
|
"default.borderWidth", float.class,
|
||||||
"default.borderColor", Color.class,
|
"default.borderColor", Color.class,
|
||||||
"default.focusedBorderColor", Color.class,
|
"default.focusedBorderColor", Color.class,
|
||||||
"default.focusColor", Color.class,
|
"default.focusColor", Color.class,
|
||||||
"default.hoverBorderColor", Color.class,
|
"default.hoverBorderColor", Color.class,
|
||||||
|
"default.pressedBorderColor", Color.class,
|
||||||
|
|
||||||
"toolbar.focusWidth", float.class,
|
"toolbar.focusWidth", float.class,
|
||||||
"toolbar.focusColor", Color.class,
|
"toolbar.focusColor", Color.class,
|
||||||
@@ -1049,6 +1080,8 @@ public class TestFlatStyleableInfo
|
|||||||
"error.focusedBorderColor", Color.class,
|
"error.focusedBorderColor", Color.class,
|
||||||
"warning.borderColor", Color.class,
|
"warning.borderColor", Color.class,
|
||||||
"warning.focusedBorderColor", Color.class,
|
"warning.focusedBorderColor", Color.class,
|
||||||
|
"success.borderColor", Color.class,
|
||||||
|
"success.focusedBorderColor", Color.class,
|
||||||
"custom.borderColor", Color.class,
|
"custom.borderColor", Color.class,
|
||||||
|
|
||||||
"outline", String.class,
|
"outline", String.class,
|
||||||
@@ -1133,6 +1166,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
|
||||||
@@ -1141,6 +1176,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,
|
||||||
@@ -1148,6 +1186,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,
|
||||||
@@ -1155,6 +1196,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,
|
||||||
@@ -1162,13 +1206,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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,9 @@ public class TestFlatStyleableValue
|
|||||||
testColor( c, ui, "buttonPressedArrowColor", 0x123456 );
|
testColor( c, ui, "buttonPressedArrowColor", 0x123456 );
|
||||||
|
|
||||||
testColor( c, ui, "popupBackground", 0x123456 );
|
testColor( c, ui, "popupBackground", 0x123456 );
|
||||||
|
testInsets( c, ui, "popupInsets", 1,2,3,4 );
|
||||||
|
testInsets( c, ui, "selectionInsets", 1,2,3,4 );
|
||||||
|
testInteger( c, ui, "selectionArc", 123 );
|
||||||
|
|
||||||
// border
|
// border
|
||||||
flatRoundBorder( c, ui );
|
flatRoundBorder( c, ui );
|
||||||
@@ -355,6 +358,7 @@ public class TestFlatStyleableValue
|
|||||||
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
||||||
|
|
||||||
testColor( c, ui, "disabledForeground", 0x123456 );
|
testColor( c, ui, "disabledForeground", 0x123456 );
|
||||||
|
testInteger( c, ui, "arc", 123 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -366,6 +370,9 @@ 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 );
|
||||||
|
testInteger( c, ui, "selectionArc", 123 );
|
||||||
|
|
||||||
// FlatListCellBorder
|
// FlatListCellBorder
|
||||||
testInsets( c, ui, "cellMargins", 1,2,3,4 );
|
testInsets( c, ui, "cellMargins", 1,2,3,4 );
|
||||||
@@ -801,6 +808,8 @@ 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", 0x901324 );
|
testColor( c, ui, "selectionInactiveForeground", 0x901324 );
|
||||||
|
testInsets( c, ui, "selectionInsets", 1,2,3,4 );
|
||||||
|
testInteger( c, ui, "selectionArc", 123 );
|
||||||
|
|
||||||
// FlatTableCellBorder
|
// FlatTableCellBorder
|
||||||
testInsets( c, ui, "cellMargins", 1,2,3,4 );
|
testInsets( c, ui, "cellMargins", 1,2,3,4 );
|
||||||
@@ -930,7 +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 );
|
||||||
|
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 );
|
||||||
@@ -955,12 +968,20 @@ public class TestFlatStyleableValue
|
|||||||
testColor( c, ui, "disabledBorderColor", 0x123456 );
|
testColor( c, ui, "disabledBorderColor", 0x123456 );
|
||||||
testColor( c, ui, "focusedBorderColor", 0x123456 );
|
testColor( c, ui, "focusedBorderColor", 0x123456 );
|
||||||
testColor( c, ui, "hoverBorderColor", 0x123456 );
|
testColor( c, ui, "hoverBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "pressedBorderColor", 0x123456 );
|
||||||
|
|
||||||
|
testColor( c, ui, "selectedBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "disabledSelectedBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "focusedSelectedBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "hoverSelectedBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "pressedSelectedBorderColor", 0x123456 );
|
||||||
|
|
||||||
testFloat( c, ui, "default.borderWidth", 1.23f );
|
testFloat( c, ui, "default.borderWidth", 1.23f );
|
||||||
testColor( c, ui, "default.borderColor", 0x123456 );
|
testColor( c, ui, "default.borderColor", 0x123456 );
|
||||||
testColor( c, ui, "default.focusedBorderColor", 0x123456 );
|
testColor( c, ui, "default.focusedBorderColor", 0x123456 );
|
||||||
testColor( c, ui, "default.focusColor", 0x123456 );
|
testColor( c, ui, "default.focusColor", 0x123456 );
|
||||||
testColor( c, ui, "default.hoverBorderColor", 0x123456 );
|
testColor( c, ui, "default.hoverBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "default.pressedBorderColor", 0x123456 );
|
||||||
|
|
||||||
testFloat( c, ui, "toolbar.focusWidth", 1.23f );
|
testFloat( c, ui, "toolbar.focusWidth", 1.23f );
|
||||||
testColor( c, ui, "toolbar.focusColor", 0x123456 );
|
testColor( c, ui, "toolbar.focusColor", 0x123456 );
|
||||||
@@ -1003,6 +1024,8 @@ public class TestFlatStyleableValue
|
|||||||
testColor( c, ui, "error.focusedBorderColor", 0x123456 );
|
testColor( c, ui, "error.focusedBorderColor", 0x123456 );
|
||||||
testColor( c, ui, "warning.borderColor", 0x123456 );
|
testColor( c, ui, "warning.borderColor", 0x123456 );
|
||||||
testColor( c, ui, "warning.focusedBorderColor", 0x123456 );
|
testColor( c, ui, "warning.focusedBorderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "success.borderColor", 0x123456 );
|
||||||
|
testColor( c, ui, "success.focusedBorderColor", 0x123456 );
|
||||||
testColor( c, ui, "custom.borderColor", 0x123456 );
|
testColor( c, ui, "custom.borderColor", 0x123456 );
|
||||||
|
|
||||||
testString( c, ui, "outline", "error" );
|
testString( c, ui, "outline", "error" );
|
||||||
@@ -1025,12 +1048,20 @@ public class TestFlatStyleableValue
|
|||||||
testValue( border, "disabledBorderColor", Color.WHITE );
|
testValue( border, "disabledBorderColor", Color.WHITE );
|
||||||
testValue( border, "focusedBorderColor", Color.WHITE );
|
testValue( border, "focusedBorderColor", Color.WHITE );
|
||||||
testValue( border, "hoverBorderColor", Color.WHITE );
|
testValue( border, "hoverBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "pressedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
|
testValue( border, "selectedBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "disabledSelectedBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "focusedSelectedBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "hoverSelectedBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "pressedSelectedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
testValue( border, "default.borderWidth", 2f );
|
testValue( border, "default.borderWidth", 2f );
|
||||||
testValue( border, "default.borderColor", Color.WHITE );
|
testValue( border, "default.borderColor", Color.WHITE );
|
||||||
testValue( border, "default.focusedBorderColor", Color.WHITE );
|
testValue( border, "default.focusedBorderColor", Color.WHITE );
|
||||||
testValue( border, "default.focusColor", Color.WHITE );
|
testValue( border, "default.focusColor", Color.WHITE );
|
||||||
testValue( border, "default.hoverBorderColor", Color.WHITE );
|
testValue( border, "default.hoverBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "default.pressedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
testValue( border, "toolbar.focusWidth", 1.5f );
|
testValue( border, "toolbar.focusWidth", 1.5f );
|
||||||
testValue( border, "toolbar.focusColor", Color.WHITE );
|
testValue( border, "toolbar.focusColor", Color.WHITE );
|
||||||
@@ -1092,6 +1123,8 @@ public class TestFlatStyleableValue
|
|||||||
testValue( border, "error.focusedBorderColor", Color.WHITE );
|
testValue( border, "error.focusedBorderColor", Color.WHITE );
|
||||||
testValue( border, "warning.borderColor", Color.WHITE );
|
testValue( border, "warning.borderColor", Color.WHITE );
|
||||||
testValue( border, "warning.focusedBorderColor", Color.WHITE );
|
testValue( border, "warning.focusedBorderColor", Color.WHITE );
|
||||||
|
testValue( border, "success.borderColor", Color.WHITE );
|
||||||
|
testValue( border, "success.focusedBorderColor", Color.WHITE );
|
||||||
testValue( border, "custom.borderColor", Color.WHITE );
|
testValue( border, "custom.borderColor", Color.WHITE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1120,6 +1153,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
|
||||||
@@ -1128,6 +1163,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 );
|
||||||
@@ -1135,6 +1173,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 );
|
||||||
@@ -1142,6 +1183,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 );
|
||||||
@@ -1149,6 +1193,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 );
|
||||||
@@ -1156,6 +1203,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
|
||||||
|
|||||||
@@ -412,6 +412,7 @@ public class TestFlatStyling
|
|||||||
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
FlatLabelUI ui = (FlatLabelUI) c.getUI();
|
||||||
|
|
||||||
ui.applyStyle( c, "disabledForeground: #fff" );
|
ui.applyStyle( c, "disabledForeground: #fff" );
|
||||||
|
ui.applyStyle( c, "arc: 8" );
|
||||||
|
|
||||||
// JComponent properties
|
// JComponent properties
|
||||||
ui.applyStyle( c, "background: #fff" );
|
ui.applyStyle( c, "background: #fff" );
|
||||||
@@ -432,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" );
|
||||||
|
|
||||||
@@ -986,6 +988,8 @@ 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( "selectionInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionArc: 8" );
|
||||||
|
|
||||||
// FlatTableCellBorder
|
// FlatTableCellBorder
|
||||||
ui.applyStyle( "cellMargins: 1,2,3,4" );
|
ui.applyStyle( "cellMargins: 1,2,3,4" );
|
||||||
@@ -1184,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" );
|
||||||
@@ -1272,6 +1278,8 @@ public class TestFlatStyling
|
|||||||
applyStyle.accept( "error.focusedBorderColor: #fff" );
|
applyStyle.accept( "error.focusedBorderColor: #fff" );
|
||||||
applyStyle.accept( "warning.borderColor: #fff" );
|
applyStyle.accept( "warning.borderColor: #fff" );
|
||||||
applyStyle.accept( "warning.focusedBorderColor: #fff" );
|
applyStyle.accept( "warning.focusedBorderColor: #fff" );
|
||||||
|
applyStyle.accept( "success.borderColor: #fff" );
|
||||||
|
applyStyle.accept( "success.focusedBorderColor: #fff" );
|
||||||
applyStyle.accept( "custom.borderColor: desaturate(#f00,50%,relative derived noAutoInverse)" );
|
applyStyle.accept( "custom.borderColor: desaturate(#f00,50%,relative derived noAutoInverse)" );
|
||||||
|
|
||||||
applyStyle.accept( "outline: error" );
|
applyStyle.accept( "outline: error" );
|
||||||
@@ -1294,12 +1302,20 @@ public class TestFlatStyling
|
|||||||
border.applyStyleProperty( "disabledBorderColor", Color.WHITE );
|
border.applyStyleProperty( "disabledBorderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "focusedBorderColor", Color.WHITE );
|
border.applyStyleProperty( "focusedBorderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "hoverBorderColor", Color.WHITE );
|
border.applyStyleProperty( "hoverBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "pressedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
|
border.applyStyleProperty( "selectedBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "disabledSelectedBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "focusedSelectedBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "hoverSelectedBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "pressedSelectedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
border.applyStyleProperty( "default.borderWidth", 2 );
|
border.applyStyleProperty( "default.borderWidth", 2 );
|
||||||
border.applyStyleProperty( "default.borderColor", Color.WHITE );
|
border.applyStyleProperty( "default.borderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "default.focusedBorderColor", Color.WHITE );
|
border.applyStyleProperty( "default.focusedBorderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "default.focusColor", Color.WHITE );
|
border.applyStyleProperty( "default.focusColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "default.hoverBorderColor", Color.WHITE );
|
border.applyStyleProperty( "default.hoverBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "default.pressedBorderColor", Color.WHITE );
|
||||||
|
|
||||||
border.applyStyleProperty( "toolbar.focusWidth", 1.5f );
|
border.applyStyleProperty( "toolbar.focusWidth", 1.5f );
|
||||||
border.applyStyleProperty( "toolbar.focusColor", Color.WHITE );
|
border.applyStyleProperty( "toolbar.focusColor", Color.WHITE );
|
||||||
@@ -1349,6 +1365,8 @@ public class TestFlatStyling
|
|||||||
border.applyStyleProperty( "error.focusedBorderColor", Color.WHITE );
|
border.applyStyleProperty( "error.focusedBorderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "warning.borderColor", Color.WHITE );
|
border.applyStyleProperty( "warning.borderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "warning.focusedBorderColor", Color.WHITE );
|
border.applyStyleProperty( "warning.focusedBorderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "success.borderColor", Color.WHITE );
|
||||||
|
border.applyStyleProperty( "success.focusedBorderColor", Color.WHITE );
|
||||||
border.applyStyleProperty( "custom.borderColor", Color.WHITE );
|
border.applyStyleProperty( "custom.borderColor", Color.WHITE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1377,6 +1395,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
|
||||||
@@ -1385,6 +1405,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 );
|
||||||
@@ -1392,6 +1415,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 );
|
||||||
@@ -1399,6 +1425,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 );
|
||||||
@@ -1406,6 +1435,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 );
|
||||||
@@ -1413,6 +1445,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
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
||||||
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
||||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user