Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e84390ee46 | ||
|
|
65a0f467ae | ||
|
|
4afb150106 | ||
|
|
0f6702217e | ||
|
|
13a0097858 | ||
|
|
01c830ad92 | ||
|
|
dce4f4623c | ||
|
|
d530624362 | ||
|
|
2e878b62d1 | ||
|
|
d27a246dfe | ||
|
|
778def118a | ||
|
|
bc5587477b | ||
|
|
03a775cd31 | ||
|
|
875083a924 | ||
|
|
f6fc925c9e | ||
|
|
74e1972781 | ||
|
|
2f5c54bb49 | ||
|
|
465798ee3d | ||
|
|
425f3acced | ||
|
|
546382e471 | ||
|
|
7e91d78633 | ||
|
|
136e1e4e30 | ||
|
|
f5f6850172 | ||
|
|
28cdde3f17 | ||
|
|
29b801e13d | ||
|
|
1435469ee5 | ||
|
|
4a0bd2c09f | ||
|
|
f8d67f863f | ||
|
|
0291dd5416 | ||
|
|
9014435d4d | ||
|
|
07ad467c73 | ||
|
|
35e23574cf | ||
|
|
9b62b8395f | ||
|
|
45e7022deb | ||
|
|
32dce16363 | ||
|
|
e34b5eafe1 | ||
|
|
4e1e749094 | ||
|
|
ede9293377 | ||
|
|
9101324a1f | ||
|
|
4b844353ee | ||
|
|
2134c19c58 | ||
|
|
c974784ebb | ||
|
|
5eb6961023 | ||
|
|
07cbd8b97b | ||
|
|
09c7f15364 | ||
|
|
b879b393ad | ||
|
|
e4503c2a54 | ||
|
|
7e2d02b997 | ||
|
|
d286550572 | ||
|
|
4e44e25d30 | ||
|
|
9fef2f9d05 | ||
|
|
04f1f5921d | ||
|
|
f9ecffb850 | ||
|
|
c9b5274ccf | ||
|
|
d209d47b9e | ||
|
|
21baaf810c | ||
|
|
95b4366270 | ||
|
|
c3adadfe2f | ||
|
|
adf7753617 | ||
|
|
d491847754 | ||
|
|
6afc747790 | ||
|
|
ff46935448 | ||
|
|
78c2f98f1f | ||
|
|
91be9aa2fe | ||
|
|
13e5da584f | ||
|
|
1762e0b7a6 | ||
|
|
05240abfe0 | ||
|
|
b515e8be04 | ||
|
|
24bc7fb0b5 | ||
|
|
0d2e1e6d18 | ||
|
|
f23c523baf | ||
|
|
76fee29f5b | ||
|
|
ec77746a43 | ||
|
|
92cd6f8f34 | ||
|
|
e7d2b5cbb6 | ||
|
|
4d175da3a0 | ||
|
|
5f047ddda9 | ||
|
|
ccca6fe88e | ||
|
|
a1f18e1ec9 | ||
|
|
afdaf7a0a5 | ||
|
|
62f0ef19f4 | ||
|
|
b736502c27 | ||
|
|
2be2dae3d6 | ||
|
|
aefe104ca4 | ||
|
|
3e6bce9cec | ||
|
|
a6394cac38 | ||
|
|
1e09ddfc93 | ||
|
|
664f5c98e9 | ||
|
|
c7bfd2ea82 | ||
|
|
9ce7ddd088 | ||
|
|
cca8d427d2 | ||
|
|
aa9263a2e7 | ||
|
|
5eaebde437 | ||
|
|
7f15f557a5 | ||
|
|
b459715cb5 | ||
|
|
bfede219d0 | ||
|
|
ef21efecf5 | ||
|
|
2bfbc9dc12 | ||
|
|
c3a1b45546 | ||
|
|
b72508f920 | ||
|
|
22bb80218d | ||
|
|
873a7e8572 | ||
|
|
0c5016fe89 | ||
|
|
607b084697 | ||
|
|
9d8ffec276 | ||
|
|
15f08e9b7c | ||
|
|
08aa6b1894 | ||
|
|
06b02c4f7c | ||
|
|
b56acd271f | ||
|
|
b24e2db59e | ||
|
|
f215356629 | ||
|
|
f7be12df67 | ||
|
|
a1d1e221ae | ||
|
|
0a4dc54fb9 | ||
|
|
b8c7801365 | ||
|
|
a7099c039f | ||
|
|
a4d2d347e3 | ||
|
|
829c537fd3 | ||
|
|
28437f99cf | ||
|
|
c1402d85e1 | ||
|
|
32e071ab89 | ||
|
|
01125e030e | ||
|
|
b43278439a | ||
|
|
7a445aabd7 | ||
|
|
380dae1017 | ||
|
|
fb15cdc546 | ||
|
|
a525fe29db | ||
|
|
bf0685cee2 | ||
|
|
8262793751 | ||
|
|
5ec7848fb0 | ||
|
|
450fc123ff | ||
|
|
3802c64be3 | ||
|
|
7bf1b26812 | ||
|
|
f1792e46c6 | ||
|
|
84e9c36280 | ||
|
|
2ef6a2c3c9 |
2
.gitattributes
vendored
@@ -20,7 +20,9 @@
|
|||||||
*.gif binary
|
*.gif binary
|
||||||
*.jar binary
|
*.jar binary
|
||||||
*.lib binary
|
*.lib binary
|
||||||
|
*.otf binary
|
||||||
*.png binary
|
*.png binary
|
||||||
*.sketch binary
|
*.sketch binary
|
||||||
*.so binary
|
*.so binary
|
||||||
|
*.ttf binary
|
||||||
*.zip binary
|
*.zip binary
|
||||||
|
|||||||
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||||
18
.github/workflows/ci.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
@@ -8,9 +9,6 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]*'
|
- '[0-9]*'
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -26,10 +24,11 @@ jobs:
|
|||||||
- 8
|
- 8
|
||||||
- 11 # LTS
|
- 11 # LTS
|
||||||
- 17 # LTS
|
- 17 # LTS
|
||||||
|
- 19
|
||||||
toolchain: [""]
|
toolchain: [""]
|
||||||
include:
|
# include:
|
||||||
- java: 17
|
# - java: 17
|
||||||
toolchain: 19 # latest
|
# toolchain: 19 # latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -54,6 +53,7 @@ jobs:
|
|||||||
name: FlatLaf-build-artifacts
|
name: FlatLaf-build-artifacts
|
||||||
path: |
|
path: |
|
||||||
flatlaf-*/build/libs
|
flatlaf-*/build/libs
|
||||||
|
flatlaf-*/flatlaf-*/build/libs
|
||||||
!**/*-javadoc.jar
|
!**/*-javadoc.jar
|
||||||
!**/*-sources.jar
|
!**/*-sources.jar
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- name: Publish snapshot to oss.sonatype.org
|
||||||
run: ./gradlew publish :flatlaf-theme-editor:build -Dorg.gradle.internal.publish.checksums.insecure=true
|
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
@@ -113,7 +113,7 @@ 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 -Drelease=true
|
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
|
|||||||
60
.github/workflows/fonts.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
|
name: Fonts
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
tags:
|
||||||
|
- 'fonts/*-[0-9]*'
|
||||||
|
paths:
|
||||||
|
- 'flatlaf-fonts/**'
|
||||||
|
- '.github/workflows/fonts.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Fonts:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
font:
|
||||||
|
- inter
|
||||||
|
- jetbrains-mono
|
||||||
|
- roboto
|
||||||
|
- roboto-mono
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: |
|
||||||
|
github.event_name == 'push' &&
|
||||||
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Java 11
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: 11
|
||||||
|
distribution: adopt # pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
|
||||||
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
|
||||||
|
|
||||||
|
- name: Publish snapshot to oss.sonatype.org
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||||
|
env:
|
||||||
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
|
if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )
|
||||||
|
|
||||||
|
- name: Release a new stable version to Maven Central
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease
|
||||||
|
env:
|
||||||
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
|
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||||
|
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||||
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )
|
||||||
10
.github/workflows/natives.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: Native Libraries
|
name: Native Libraries
|
||||||
|
|
||||||
@@ -12,13 +13,6 @@ on:
|
|||||||
- 'flatlaf-natives/**'
|
- 'flatlaf-natives/**'
|
||||||
- '.github/workflows/natives.yml'
|
- '.github/workflows/natives.yml'
|
||||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
paths:
|
|
||||||
- 'flatlaf-natives/**'
|
|
||||||
- '.github/workflows/natives.yml'
|
|
||||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Natives:
|
Natives:
|
||||||
|
|||||||
2
.gitignore
vendored
@@ -9,5 +9,7 @@ out/
|
|||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
|
*.xcuserstate
|
||||||
|
*.xcworkspacedata
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
111
CHANGELOG.md
@@ -1,6 +1,117 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
## 3.1.1
|
||||||
|
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Fixed too large menu item paddings and too large table/tree row heights (all
|
||||||
|
"Material Theme UI Lite" themes; issue #667; regression in FlatLaf 3.1).
|
||||||
|
- Fixed too large tree row height in "Carbon", "Dark Purple", "Gray",
|
||||||
|
"Material Design Dark", "Monokai Pro", "One Dark" and "Spacegray" themes.
|
||||||
|
- Native libraries: Fixed `IllegalArgumentException: URI scheme is not "file"`
|
||||||
|
when using FlatLaf in WebStart. (issue #668; regression in FlatLaf 3.1)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.1
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- Windows 11: Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
||||||
|
native Windows 11 rounded borders and drop shadows. (PR #643)
|
||||||
|
- Fonts:
|
||||||
|
- Added **Roboto Mono** (https://fonts.google.com/specimen/Roboto+Mono). (PR
|
||||||
|
#639, issue #638)
|
||||||
|
- Updated **JetBrains Mono** to
|
||||||
|
[v2.304](https://github.com/JetBrains/JetBrainsMono/releases/tag/v2.304).
|
||||||
|
- Theme Editor: Support macOS light and dark themes.
|
||||||
|
- TabbedPane: Support hover and focused tab foreground colors. (issue #627)
|
||||||
|
- TabbedPane: `tabbedPane.getBackgroundAt(tabIndex)` now has higher priority
|
||||||
|
than `TabbedPane.focusColor` and `TabbedPane.selectedBackground`. If
|
||||||
|
`tabbedPane.setBackgroundAt(tabIndex)` is used to set a color for a single
|
||||||
|
tab, then this color is now used even if the tab is focused or selected.
|
||||||
|
- TableHeader: Support column hover and pressed background and foreground
|
||||||
|
colors. (issue #636)
|
||||||
|
- Native libraries: Made it easier to distribute FlatLaf native libraries
|
||||||
|
(Windows `.dll` and Linux `.so`) to avoid problems on operating systems with
|
||||||
|
enabled execution restrictions.
|
||||||
|
See https://www.formdev.com/flatlaf/native-libraries/ for more details. (issue #624)
|
||||||
|
- Published native libraries to Maven Central for easy using them as
|
||||||
|
dependencies in Gradle and Maven.
|
||||||
|
- If available, native libraries are now loaded from same location as
|
||||||
|
`flatlaf.jar`, otherwise they are extract from `flatlaf.jar` to temporary
|
||||||
|
folder and loaded from there.
|
||||||
|
- Windows DLLs are now digitally signed with FormDev Software GmbH
|
||||||
|
certificate.
|
||||||
|
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- FlatLaf window decorations:
|
||||||
|
- Fixed inconsistent size of glass pane depending on whether FlatLaf window
|
||||||
|
decorations are used (e.g. Windows 10/11) or not (e.g. macOS). Now the glass
|
||||||
|
pane no longer overlaps the FlatLaf window title bar. (issue #630)
|
||||||
|
- Linux: Fixed broken window resizing on multi-screen setups. (issue #632)
|
||||||
|
- Linux: Fixed behavior of maximize/restore button when tiling window to left
|
||||||
|
or right half of screen. (issue #647)
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Fixed default button hover background in "Solarized Light" theme. (issue
|
||||||
|
#628)
|
||||||
|
- Avoid that accent color affect some colors in some IntelliJ themes. (issue
|
||||||
|
#625)
|
||||||
|
- Updated "Hiberbee Dark" and "Material Theme UI Lite" themes.
|
||||||
|
- Styling: Fixed resolving of UI variables in styles that use other variables.
|
||||||
|
- MenuItem: Fixed horizontal alignment of icons. (issue #631)
|
||||||
|
- Table: Fixed potential performance issue with paint cell focus indicator
|
||||||
|
border. (issue #654)
|
||||||
|
- Tree: Fixed missing custom closed/opened/leaf icons of a custom
|
||||||
|
`DefaultTreeCellRenderer`. (issue #653; regression since implementing PR #609
|
||||||
|
in FlatLaf 3.0)
|
||||||
|
- Tree: Fixed truncated node text and too small painted non-wide node background
|
||||||
|
if custom cell renderer sets icon, but not disabled icon, and tree is
|
||||||
|
disabled. (issue #640)
|
||||||
|
- Fixed `HiDPIUtils.paintAtScale1x()`, which painted at wrong location if
|
||||||
|
graphics is rotated, is scaled and `x` or `y` parameters are not zero. (issue
|
||||||
|
#646)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.0
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- **macOS light and dark themes**: The two new themes `FlatMacLightLaf` and
|
||||||
|
`FlatMacDarkLaf` use macOS colors and look similar to native macOS controls.
|
||||||
|
(PRs #533, #612 and #607)
|
||||||
|
- **Fonts**: Packaged some fonts into JARs and provide an easy way to use them
|
||||||
|
with FlatLaf. (PRs #545, #614 and #615) At the moment there are three fonts:
|
||||||
|
- **Inter** (https://rsms.me/inter/) - a typeface carefully crafted & designed
|
||||||
|
for computer screens
|
||||||
|
- **Roboto** (https://fonts.google.com/specimen/Roboto) - default font on
|
||||||
|
Android and recommended for Material Design
|
||||||
|
- **JetBrains Mono** (https://www.jetbrains.com/mono) - a monospaced typeface
|
||||||
|
- **Rounded selection**: Optionally use rounded selection in:
|
||||||
|
- Menus (PR #536)
|
||||||
|
- ComboBox (PR #548)
|
||||||
|
- List (PR #547)
|
||||||
|
- Tree (PR #546)
|
||||||
|
- Tree: Hide default closed/opened/leaf icons by default. Set UI value
|
||||||
|
`Tree.showDefaultIcons` to `true` to show them.
|
||||||
|
- ToolBar: Hover effect for button groups. (PR #534)
|
||||||
|
- Icons: New modern **rounded outlined icons** for `JFileChooser`,
|
||||||
|
`JOptionPane`, `JPasswordField` and `JTree`. (PR #577)
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- FileChooser: Fixed layout of (optional) accessory component and fixed too
|
||||||
|
large right margin. (issue #604; regression since implementing PR #522 in
|
||||||
|
FlatLaf 2.3)
|
||||||
|
- Tree:
|
||||||
|
- Fixed missing tree lines (if enabled) for wide-selected rows. (issue #598)
|
||||||
|
- Fixed scaling of tree lines and fixed alignment to expand/collapse arrows.
|
||||||
|
- Removed support for dashed tree lines. `Tree.lineTypeDashed` is now ignored.
|
||||||
|
- SwingX: Fonts in `JXHeader`, `JXMonthView`, `JXTaskPane` and `JXTitledPanel`
|
||||||
|
were not updated when changing default font.
|
||||||
|
|
||||||
|
|
||||||
## 2.6
|
## 2.6
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
|
|||||||
95
README.md
@@ -15,6 +15,11 @@ IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
macOS Themes
|
||||||
|
------------
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
IntelliJ Platform Themes
|
IntelliJ Platform Themes
|
||||||
------------------------
|
------------------------
|
||||||
@@ -25,6 +30,17 @@ FlatLaf can use 3rd party themes created for IntelliJ Platform (see
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
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.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>
|
||||||
|
|
||||||
|
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
|
||||||
|
|
||||||
Demo
|
Demo
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -50,6 +66,11 @@ Otherwise download `flatlaf-<version>.jar` here:
|
|||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
||||||
|
|
||||||
|
See also
|
||||||
|
[Native Libraries distribution](https://www.formdev.com/flatlaf/native-libraries/)
|
||||||
|
for instructions on how to redistribute FlatLaf native libraries with your
|
||||||
|
application.
|
||||||
|
|
||||||
|
|
||||||
### Snapshots
|
### Snapshots
|
||||||
|
|
||||||
@@ -74,6 +95,8 @@ Addons
|
|||||||
- [SwingX](flatlaf-swingx) - support for SwingX components
|
- [SwingX](flatlaf-swingx) - support for SwingX components
|
||||||
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
||||||
components
|
components
|
||||||
|
- [Fonts](flatlaf-fonts) - some font families bundled in easy-to-use and
|
||||||
|
redistributable JARs
|
||||||
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
@@ -126,42 +149,64 @@ Buzz
|
|||||||
Applications using FlatLaf
|
Applications using FlatLaf
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
- 
|
||||||
|
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||||
|
12 (**commercial**) - the award-winning all-in-one Java profiler
|
||||||
|
-  [JFormDesigner](https://www.formdev.com/) 8
|
||||||
|
(**commercial**) - Java/Swing GUI Designer
|
||||||
|
-  [Jeyla Studio](https://www.jeylastudio.com/) - Salon
|
||||||
|
Software
|
||||||
|
-  [Fanurio](https://www.fanuriotimetracking.com/) 3.3.2
|
||||||
|
(**commercial**) - time tracking and billing for freelancers and teams
|
||||||
|
-  [Antares](https://www.antarescircuit.io/) - a free,
|
||||||
|
powerful platform for designing, simulating and explaining digital circuits
|
||||||
|
- 
|
||||||
|
[Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution)
|
||||||
|
3.6 - Digital logic design tool and simulator
|
||||||
|
-  [Cinecred](https://loadingbyte.com/cinecred/) - create
|
||||||
|
beautiful film credit sequences
|
||||||
|
-  [tinyMediaManager](https://www.tinymediamanager.org/)
|
||||||
|
v4 (**commercial**) - a media management tool
|
||||||
|
-  [Weasis](https://nroduit.github.io/) - medical DICOM
|
||||||
|
viewer used in healthcare by hospitals, health networks, etc
|
||||||
|
- 
|
||||||
|
[Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software)
|
||||||
|
7.3.0 - for plotters, especially the wall-hanging polargraph
|
||||||
|
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||||
visual query system for relational databases
|
visual query system for relational databases
|
||||||
-  [MooInfo](https://github.com/rememberber/MooInfo) -
|
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||||
visual implementation of OSHI, to view information about the system and
|
OSHI, to view information about the system and hardware
|
||||||
hardware
|
- [Jailer](https://github.com/Wisser/Jailer) 11.2 - database subsetting and
|
||||||
-  [Jailer](https://github.com/Wisser/Jailer) 11.2 -
|
relational data browsing tool
|
||||||
database subsetting and relational data browsing tool
|
-  [Apache NetBeans](https://netbeans.apache.org/) 11.3 -
|
||||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
IDE for Java, PHP, HTML and much more
|
||||||
and much more
|
|
||||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||||
- 
|
- 
|
||||||
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
||||||
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
||||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
||||||
(**commercial**) - the universal database tool for developers, analysts and
|
(**commercial**) - the universal database tool for developers, analysts and
|
||||||
DBAs
|
DBAs
|
||||||
-  [MagicPlot](https://magicplot.com/) 3.0
|
-  [MagicPlot](https://magicplot.com/) 3.0
|
||||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
||||||
- 
|
- 
|
||||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
||||||
(**commercial**) - Thermodynamics and Properties Software
|
(**commercial**) - Thermodynamics and Properties Software
|
||||||
- [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds most widely used web
|
-  [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds
|
||||||
app scanner
|
most widely used web app scanner
|
||||||
- 
|
- 
|
||||||
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
||||||
2020.11.2 (**commercial**) - the leading software for web security testing
|
2020.11.2 (**commercial**) - the leading software for web security testing
|
||||||
- 
|
- [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
|
||||||
- [JOSM](https://josm.openstreetmap.de/) - an extensible editor for
|
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
||||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
||||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
JOSM plugin)
|
||||||
websites
|
-  [jAlbum](https://jalbum.net/) 21 (**commercial**) -
|
||||||
-  [PDF Studio](https://www.qoppa.com/pdfstudio/) 2021
|
creates photo album websites
|
||||||
(**commercial**) - create, review and edit PDF documents
|
- [PDF Studio](https://www.qoppa.com/pdfstudio/) 2021 (**commercial**) - create,
|
||||||
|
review and edit PDF documents
|
||||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
||||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||||
checks your website
|
checks your website
|
||||||
@@ -187,8 +232,8 @@ Applications using FlatLaf
|
|||||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||||
[AS4](https://mendelson-e-c.com/as4/) and
|
[AS4](https://mendelson-e-c.com/as4/) and
|
||||||
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
||||||
-  [IGMAS+](https://www.gfz-potsdam.de/igmas) -
|
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||||
Interactive Gravity and Magnetic Application System
|
Application System
|
||||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
||||||
computation environment for meteorological community
|
computation environment for meteorological community
|
||||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val releaseVersion = "2.6"
|
val releaseVersion = "3.1.1"
|
||||||
val developmentVersion = "3.0-SNAPSHOT"
|
val developmentVersion = "3.2-SNAPSHOT"
|
||||||
|
|
||||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
version = if( rootProject.hasProperty( "release" ) ) releaseVersion else developmentVersion
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
open class NativeArtifact( val fileName: String, val classifier: String, val type: String ) {}
|
||||||
|
|
||||||
open class PublishExtension {
|
open class PublishExtension {
|
||||||
var artifactId: String? = null
|
var artifactId: String? = null
|
||||||
var name: String? = null
|
var name: String? = null
|
||||||
var description: String? = null
|
var description: String? = null
|
||||||
|
var nativeArtifacts: List<NativeArtifact>? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||||
@@ -71,6 +74,15 @@ publishing {
|
|||||||
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
|
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
extension.nativeArtifacts?.forEach {
|
||||||
|
artifact( artifacts.add( "archives", file( it.fileName ) ) {
|
||||||
|
classifier = it.classifier
|
||||||
|
type = it.type
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +92,7 @@ publishing {
|
|||||||
|
|
||||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||||
url = uri( if( java.lang.Boolean.getBoolean( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
// get from gradle.properties
|
// get from gradle.properties
|
||||||
@@ -108,5 +120,5 @@ signing {
|
|||||||
|
|
||||||
// disable signing of snapshots
|
// disable signing of snapshots
|
||||||
tasks.withType<Sign>().configureEach {
|
tasks.withType<Sign>().configureEach {
|
||||||
onlyIf { java.lang.Boolean.getBoolean( "release" ) }
|
onlyIf { rootProject.hasProperty( "release" ) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Flatlaf_publish_gradle.NativeArtifact
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`flatlaf-toolchain`
|
`flatlaf-toolchain`
|
||||||
@@ -87,7 +89,7 @@ tasks {
|
|||||||
"action" to "generate",
|
"action" to "generate",
|
||||||
"fileName" to "${project.name}-sigtest.txt",
|
"fileName" to "${project.name}-sigtest.txt",
|
||||||
"classpath" to jar.get().outputs.files.asPath,
|
"classpath" to jar.get().outputs.files.asPath,
|
||||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util",
|
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.themes,com.formdev.flatlaf.util",
|
||||||
"version" to version,
|
"version" to version,
|
||||||
"release" to "1.8", // Java version
|
"release" to "1.8", // Java version
|
||||||
"failonerror" to "true" )
|
"failonerror" to "true" )
|
||||||
@@ -123,4 +125,11 @@ flatlafPublish {
|
|||||||
artifactId = "flatlaf"
|
artifactId = "flatlaf"
|
||||||
name = "FlatLaf"
|
name = "FlatLaf"
|
||||||
description = "Flat Look and Feel"
|
description = "Flat Look and Feel"
|
||||||
|
|
||||||
|
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
||||||
|
nativeArtifacts = listOf(
|
||||||
|
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
|
||||||
|
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
|
||||||
|
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Signature file v4.1
|
#Signature file v4.1
|
||||||
#Version 2.5
|
#Version 3.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"
|
||||||
@@ -12,6 +12,7 @@ fld public final static java.lang.String BUTTON_TYPE_TOOLBAR_BUTTON = "toolBarBu
|
|||||||
fld public final static java.lang.String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner"
|
fld public final static java.lang.String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner"
|
||||||
fld public final static java.lang.String COMPONENT_ROUND_RECT = "JComponent.roundRect"
|
fld public final static java.lang.String COMPONENT_ROUND_RECT = "JComponent.roundRect"
|
||||||
fld public final static java.lang.String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption"
|
fld public final static java.lang.String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption"
|
||||||
|
fld public final static java.lang.String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight"
|
||||||
fld public final static java.lang.String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"
|
fld public final static java.lang.String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"
|
||||||
fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHeight"
|
fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHeight"
|
||||||
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
||||||
@@ -19,6 +20,7 @@ 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_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_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted"
|
fld public final static java.lang.String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted"
|
||||||
fld public final static java.lang.String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight"
|
fld public final static java.lang.String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight"
|
||||||
fld public final static java.lang.String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight"
|
fld public final static java.lang.String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight"
|
||||||
@@ -86,7 +88,11 @@ 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_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_MAXIMIZE = "JRootPane.titleBarShowMaximize"
|
||||||
|
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_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"
|
||||||
@@ -195,8 +201,13 @@ meth public static boolean isUseNativeWindowDecorations()
|
|||||||
meth public static boolean setup(javax.swing.LookAndFeel)
|
meth public static boolean setup(javax.swing.LookAndFeel)
|
||||||
meth public static boolean supportsNativeWindowDecorations()
|
meth public static boolean supportsNativeWindowDecorations()
|
||||||
meth public static java.lang.Object parseDefaultsValue(java.lang.String,java.lang.String,java.lang.Class<?>)
|
meth public static java.lang.Object parseDefaultsValue(java.lang.String,java.lang.String,java.lang.Class<?>)
|
||||||
|
meth public static java.lang.String getPreferredFontFamily()
|
||||||
|
meth public static java.lang.String getPreferredLightFontFamily()
|
||||||
|
meth public static java.lang.String getPreferredMonospacedFontFamily()
|
||||||
|
meth public static java.lang.String getPreferredSemiboldFontFamily()
|
||||||
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.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 hideMnemonics()
|
meth public static void hideMnemonics()
|
||||||
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
||||||
@@ -209,6 +220,11 @@ meth public static void repaintAllFramesAndDialogs()
|
|||||||
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
||||||
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
||||||
meth public static void setGlobalExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
meth public static void setGlobalExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||||
|
meth public static void setPreferredFontFamily(java.lang.String)
|
||||||
|
meth public static void setPreferredLightFontFamily(java.lang.String)
|
||||||
|
meth public static void setPreferredMonospacedFontFamily(java.lang.String)
|
||||||
|
meth public static void setPreferredSemiboldFontFamily(java.lang.String)
|
||||||
|
meth public static void setSystemColorGetter(java.util.function.Function<java.lang.String,java.awt.Color>)
|
||||||
meth public static void setUseNativeWindowDecorations(boolean)
|
meth public static void setUseNativeWindowDecorations(boolean)
|
||||||
meth public static void showMnemonics(java.awt.Component)
|
meth public static void showMnemonics(java.awt.Component)
|
||||||
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
||||||
@@ -223,7 +239,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,getUIMethod,getUIMethodInitialized,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,subMenuUsabilityHelperInstalled,uiDefaultsGetters,updateUIPending
|
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,getUIMethod,getUIMethodInitialized,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,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
|
||||||
@@ -295,6 +311,26 @@ meth public java.lang.String getName()
|
|||||||
supr com.formdev.flatlaf.FlatLaf
|
supr com.formdev.flatlaf.FlatLaf
|
||||||
hfds theme
|
hfds theme
|
||||||
|
|
||||||
|
CLSS public com.formdev.flatlaf.themes.FlatMacDarkLaf
|
||||||
|
cons public init()
|
||||||
|
fld public final static java.lang.String NAME = "FlatLaf macOS Dark"
|
||||||
|
meth public boolean isDark()
|
||||||
|
meth public java.lang.String getDescription()
|
||||||
|
meth public java.lang.String getName()
|
||||||
|
meth public static boolean setup()
|
||||||
|
meth public static void installLafInfo()
|
||||||
|
supr com.formdev.flatlaf.FlatDarkLaf
|
||||||
|
|
||||||
|
CLSS public com.formdev.flatlaf.themes.FlatMacLightLaf
|
||||||
|
cons public init()
|
||||||
|
fld public final static java.lang.String NAME = "FlatLaf macOS Light"
|
||||||
|
meth public boolean isDark()
|
||||||
|
meth public java.lang.String getDescription()
|
||||||
|
meth public java.lang.String getName()
|
||||||
|
meth public static boolean setup()
|
||||||
|
meth public static void installLafInfo()
|
||||||
|
supr com.formdev.flatlaf.FlatLightLaf
|
||||||
|
|
||||||
CLSS public abstract interface com.formdev.flatlaf.util.AnimatedIcon
|
CLSS public abstract interface com.formdev.flatlaf.util.AnimatedIcon
|
||||||
innr public static AnimationSupport
|
innr public static AnimationSupport
|
||||||
intf javax.swing.Icon
|
intf javax.swing.Icon
|
||||||
@@ -362,6 +398,7 @@ meth public static float clamp(float)
|
|||||||
meth public static float luma(java.awt.Color)
|
meth public static float luma(java.awt.Color)
|
||||||
meth public static java.awt.Color darken(java.awt.Color,float)
|
meth public static java.awt.Color darken(java.awt.Color,float)
|
||||||
meth public static java.awt.Color desaturate(java.awt.Color,float)
|
meth public static java.awt.Color desaturate(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color fade(java.awt.Color,float)
|
||||||
meth public static java.awt.Color lighten(java.awt.Color,float)
|
meth public static java.awt.Color lighten(java.awt.Color,float)
|
||||||
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
||||||
meth public static java.awt.Color saturate(java.awt.Color,float)
|
meth public static java.awt.Color saturate(java.awt.Color,float)
|
||||||
@@ -437,6 +474,17 @@ meth public java.lang.String toString()
|
|||||||
supr javax.swing.plaf.ColorUIResource
|
supr javax.swing.plaf.ColorUIResource
|
||||||
hfds baseOfDefaultColorRGB,functions,hasBaseOfDefaultColor
|
hfds baseOfDefaultColorRGB,functions,hasBaseOfDefaultColor
|
||||||
|
|
||||||
|
CLSS public com.formdev.flatlaf.util.FontUtils
|
||||||
|
cons public init()
|
||||||
|
meth public static boolean installFont(java.net.URL)
|
||||||
|
meth public static java.awt.Font getCompositeFont(java.lang.String,int,int)
|
||||||
|
meth public static java.awt.Font[] getAllFonts()
|
||||||
|
meth public static java.lang.String[] getAvailableFontFamilyNames()
|
||||||
|
meth public static void loadFontFamily(java.lang.String)
|
||||||
|
meth public static void registerFontFamilyLoader(java.lang.String,java.lang.Runnable)
|
||||||
|
supr java.lang.Object
|
||||||
|
hfds loadersMap
|
||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.Graphics2DProxy
|
CLSS public com.formdev.flatlaf.util.Graphics2DProxy
|
||||||
cons public init(java.awt.Graphics2D)
|
cons public init(java.awt.Graphics2D)
|
||||||
meth public boolean drawImage(java.awt.Image,int,int,int,int,int,int,int,int,java.awt.Color,java.awt.image.ImageObserver)
|
meth public boolean drawImage(java.awt.Image,int,int,int,int,int,int,int,int,java.awt.Color,java.awt.image.ImageObserver)
|
||||||
@@ -573,7 +621,7 @@ meth public static void drawStringWithYCorrection(javax.swing.JComponent,java.aw
|
|||||||
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)
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
hfds 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$Painter
|
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$Painter
|
||||||
outer com.formdev.flatlaf.util.HiDPIUtils
|
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||||
@@ -604,6 +652,7 @@ supr java.lang.Object
|
|||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
||||||
cons public init(java.io.File,boolean)
|
cons public init(java.io.File,boolean)
|
||||||
|
cons public init(java.lang.String,boolean)
|
||||||
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
||||||
meth public boolean isLoaded()
|
meth public boolean isLoaded()
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|||||||
@@ -268,6 +268,25 @@ public interface FlatClientProperties
|
|||||||
|
|
||||||
//---- Popup --------------------------------------------------------------
|
//---- Popup --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the popup border corner radius if the component is shown in a popup
|
||||||
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
|
* <p>
|
||||||
|
* Note that this is not available on all platforms since it requires special support.
|
||||||
|
* Supported platforms:
|
||||||
|
* <p>
|
||||||
|
* <strong>Windows 11</strong> (x86 or x86_64): Only two corner radiuses are supported
|
||||||
|
* by the OS: {@code DWMWCP_ROUND} is 8px and {@code DWMWCP_ROUNDSMALL} is 4px.
|
||||||
|
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
|
||||||
|
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||||
* or if the component is the owner of another component that is shown in a popup.
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
@@ -346,7 +365,7 @@ public interface FlatClientProperties
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the window icon should be shown in the window title bar
|
* Specifies whether the window icon should be shown in the window title bar
|
||||||
* (requires enabled window decorations).
|
* (requires enabled window decorations). Default is UI property {@code TitlePane.showIcon}.
|
||||||
* <p>
|
* <p>
|
||||||
* Setting this shows/hides the windows icon
|
* Setting this shows/hides the windows icon
|
||||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
@@ -362,6 +381,62 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the window title should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the windows title
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "iconfify" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "iconfify" button
|
||||||
|
* for the {@code JFrame} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "maximize/restore" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "maximize/restore" button
|
||||||
|
* for the {@code JFrame} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "close" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "close" button
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background color of window title bar (requires enabled window decorations).
|
* Background color of window title bar (requires enabled window decorations).
|
||||||
* <p>
|
* <p>
|
||||||
@@ -386,6 +461,17 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the glass pane should have full height and overlap the title bar,
|
||||||
|
* if FlatLaf window decorations are enabled. Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight";
|
||||||
|
|
||||||
//---- JScrollBar / JScrollPane -------------------------------------------
|
//---- JScrollBar / JScrollPane -------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import com.formdev.flatlaf.ui.FlatPopupFactory;
|
|||||||
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.FontUtils;
|
||||||
import com.formdev.flatlaf.util.GrayFilter;
|
import com.formdev.flatlaf.util.GrayFilter;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||||
@@ -98,6 +99,7 @@ public abstract class FlatLaf
|
|||||||
private static List<Object> customDefaultsSources;
|
private static List<Object> customDefaultsSources;
|
||||||
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 String desktopPropertyName;
|
private String desktopPropertyName;
|
||||||
private String desktopPropertyName2;
|
private String desktopPropertyName2;
|
||||||
@@ -113,6 +115,11 @@ public abstract class FlatLaf
|
|||||||
private Consumer<UIDefaults> postInitialization;
|
private Consumer<UIDefaults> postInitialization;
|
||||||
private List<Function<Object, Object>> uiDefaultsGetters;
|
private List<Function<Object, Object>> uiDefaultsGetters;
|
||||||
|
|
||||||
|
private static String preferredFontFamily;
|
||||||
|
private static String preferredLightFontFamily;
|
||||||
|
private static String preferredSemiboldFontFamily;
|
||||||
|
private static String preferredMonospacedFontFamily;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)}.
|
||||||
@@ -630,6 +637,13 @@ public abstract class FlatLaf
|
|||||||
if( uiFont == null )
|
if( uiFont == null )
|
||||||
uiFont = createCompositeFont( Font.SANS_SERIF, Font.PLAIN, 12 );
|
uiFont = createCompositeFont( Font.SANS_SERIF, Font.PLAIN, 12 );
|
||||||
|
|
||||||
|
// use preferred font family (if specified)
|
||||||
|
if( preferredFontFamily != null ) {
|
||||||
|
FontUIResource preferredFont = createCompositeFont( preferredFontFamily, uiFont.getStyle(), uiFont.getSize() );
|
||||||
|
if( !ActiveFont.isFallbackFont( preferredFont ) || ActiveFont.isDialogFamily( preferredFontFamily ) )
|
||||||
|
uiFont = preferredFont;
|
||||||
|
}
|
||||||
|
|
||||||
// get/remove "defaultFont" from defaults if set in properties files
|
// get/remove "defaultFont" from defaults if set in properties files
|
||||||
// (use remove() to avoid that ActiveFont.createValue() gets invoked)
|
// (use remove() to avoid that ActiveFont.createValue() gets invoked)
|
||||||
Object defaultFont = defaults.remove( "defaultFont" );
|
Object defaultFont = defaults.remove( "defaultFont" );
|
||||||
@@ -650,6 +664,9 @@ public abstract class FlatLaf
|
|||||||
}
|
}
|
||||||
|
|
||||||
static FontUIResource createCompositeFont( String family, int style, int size ) {
|
static FontUIResource createCompositeFont( String family, int style, int size ) {
|
||||||
|
// load lazy font family
|
||||||
|
FontUtils.loadFontFamily( family );
|
||||||
|
|
||||||
// using StyleContext.getFont() here because it uses
|
// using StyleContext.getFont() here because it uses
|
||||||
// sun.font.FontUtilities.getCompositeFontUIResource()
|
// sun.font.FontUtilities.getCompositeFontUIResource()
|
||||||
// and creates a composite font that is able to display all Unicode characters
|
// and creates a composite font that is able to display all Unicode characters
|
||||||
@@ -897,14 +914,14 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
* Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
* <p>
|
* <p>
|
||||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||||
* FlatLightLaf.setup();
|
* FlatLightLaf.setup();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
@@ -929,15 +946,15 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The extra defaults are useful for smaller additional defaults that may change.
|
* The extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
* Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
* <p>
|
* <p>
|
||||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FlatLaf laf = new FlatLightLaf();
|
* FlatLaf laf = new FlatLightLaf();
|
||||||
* laf.setExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
* laf.setExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||||
* FlatLaf.setup( laf );
|
* FlatLaf.setup( laf );
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
@@ -979,6 +996,36 @@ public abstract class FlatLaf
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the system color getter function, or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static Function<String, Color> getSystemColorGetter() {
|
||||||
|
return systemColorGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a system color getter function that is invoked when function
|
||||||
|
* {@code systemColor()} is used in FlatLaf properties files.
|
||||||
|
* <p>
|
||||||
|
* The name of the system color is passed as parameter to the function.
|
||||||
|
* The function should return {@code null} for unknown system colors.
|
||||||
|
* <p>
|
||||||
|
* Can be used to change the accent color:
|
||||||
|
* <pre>{@code
|
||||||
|
* FlatLaf.setSystemColorGetter( name -> {
|
||||||
|
* return name.equals( "accent" ) ? Color.red : null;
|
||||||
|
* } );
|
||||||
|
* FlatLightLaf.setup();
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setSystemColorGetter( Function<String, Color> systemColorGetter ) {
|
||||||
|
FlatLaf.systemColorGetter = systemColorGetter;
|
||||||
|
}
|
||||||
|
|
||||||
private static void reSetLookAndFeel() {
|
private static void reSetLookAndFeel() {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||||
@@ -1292,6 +1339,90 @@ public abstract class FlatLaf
|
|||||||
private static boolean getUIMethodInitialized;
|
private static boolean getUIMethodInitialized;
|
||||||
private static MethodHandle getUIMethod;
|
private static MethodHandle getUIMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred font family to be used for (nearly) all fonts; or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static String getPreferredFontFamily() {
|
||||||
|
return preferredFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred font family to be used for (nearly) all fonts.
|
||||||
|
* <p>
|
||||||
|
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||||
|
* the application look and feel.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setPreferredFontFamily( String preferredFontFamily ) {
|
||||||
|
FlatLaf.preferredFontFamily = preferredFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred font family to be used for "light" fonts; or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static String getPreferredLightFontFamily() {
|
||||||
|
return preferredLightFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred font family to be used for "light" fonts.
|
||||||
|
* <p>
|
||||||
|
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||||
|
* the application look and feel.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setPreferredLightFontFamily( String preferredLightFontFamily ) {
|
||||||
|
FlatLaf.preferredLightFontFamily = preferredLightFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred font family to be used for "semibold" fonts; or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static String getPreferredSemiboldFontFamily() {
|
||||||
|
return preferredSemiboldFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred font family to be used for "semibold" fonts.
|
||||||
|
* <p>
|
||||||
|
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||||
|
* the application look and feel.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setPreferredSemiboldFontFamily( String preferredSemiboldFontFamily ) {
|
||||||
|
FlatLaf.preferredSemiboldFontFamily = preferredSemiboldFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred font family to be used for monospaced fonts; or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static String getPreferredMonospacedFontFamily() {
|
||||||
|
return preferredMonospacedFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred font family to be used for monospaced fonts.
|
||||||
|
* <p>
|
||||||
|
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||||
|
* the application look and feel.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setPreferredMonospacedFontFamily( String preferredMonospacedFontFamily ) {
|
||||||
|
FlatLaf.preferredMonospacedFontFamily = preferredMonospacedFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatUIDefaults -----------------------------------------------
|
//---- class FlatUIDefaults -----------------------------------------------
|
||||||
|
|
||||||
private class FlatUIDefaults
|
private class FlatUIDefaults
|
||||||
@@ -1426,9 +1557,16 @@ public abstract class FlatLaf
|
|||||||
|
|
||||||
// create font for family
|
// create font for family
|
||||||
if( families != null && !families.isEmpty() ) {
|
if( families != null && !families.isEmpty() ) {
|
||||||
|
String preferredFamily = preferredFamily( families );
|
||||||
|
if( preferredFamily != null ) {
|
||||||
|
Font font = createCompositeFont( preferredFamily, newStyle, newSize );
|
||||||
|
if( !isFallbackFont( font ) || isDialogFamily( preferredFamily ) )
|
||||||
|
return toUIResource( font );
|
||||||
|
}
|
||||||
|
|
||||||
for( String family : families ) {
|
for( String family : families ) {
|
||||||
Font font = createCompositeFont( family, newStyle, newSize );
|
Font font = createCompositeFont( family, newStyle, newSize );
|
||||||
if( !isFallbackFont( font ) || family.equalsIgnoreCase( Font.DIALOG ) )
|
if( !isFallbackFont( font ) || isDialogFamily( family ) )
|
||||||
return toUIResource( font );
|
return toUIResource( font );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1457,9 +1595,26 @@ public abstract class FlatLaf
|
|||||||
: new FontUIResource( font );
|
: new FontUIResource( font );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFallbackFont( Font font ) {
|
private static boolean isFallbackFont( Font font ) {
|
||||||
return Font.DIALOG.equalsIgnoreCase( font.getFamily() );
|
return Font.DIALOG.equalsIgnoreCase( font.getFamily() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isDialogFamily( String family ) {
|
||||||
|
return family.equalsIgnoreCase( Font.DIALOG );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String preferredFamily( List<String> families ) {
|
||||||
|
for( String family : families ) {
|
||||||
|
family = family.toLowerCase( Locale.ENGLISH );
|
||||||
|
if( family.endsWith( " light" ) || family.endsWith( "-thin" ) )
|
||||||
|
return preferredLightFontFamily;
|
||||||
|
if( family.endsWith( " semibold" ) || family.endsWith( "-medium" ) )
|
||||||
|
return preferredSemiboldFontFamily;
|
||||||
|
if( family.equals( "monospaced" ) )
|
||||||
|
return preferredMonospacedFontFamily;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class ImageIconUIResource ------------------------------------------
|
//---- class ImageIconUIResource ------------------------------------------
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
ColorUIResource color = UIDefaultsLoader.parseColor( value );
|
ColorUIResource color = parseColor( value );
|
||||||
if( color != null ) {
|
if( color != null ) {
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
namedColors.put( key, color );
|
namedColors.put( key, color );
|
||||||
@@ -336,8 +336,13 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
uiKeys.add( key );
|
uiKeys.add( key );
|
||||||
|
|
||||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
// ignore some properties that affect sizes
|
||||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
if( key.endsWith( ".border" ) ||
|
||||||
|
key.endsWith( ".rowHeight" ) ||
|
||||||
|
key.equals( "ComboBox.padding" ) ||
|
||||||
|
key.equals( "Spinner.padding" ) ||
|
||||||
|
key.equals( "Tree.leftChildIndent" ) ||
|
||||||
|
key.equals( "Tree.rightChildIndent" ) )
|
||||||
return; // ignore
|
return; // ignore
|
||||||
|
|
||||||
// map keys
|
// map keys
|
||||||
@@ -448,7 +453,15 @@ public class IntelliJTheme
|
|||||||
ColorUIResource color = namedColors.get( value );
|
ColorUIResource color = namedColors.get( value );
|
||||||
|
|
||||||
// parse color
|
// parse color
|
||||||
return (color != null) ? color : UIDefaultsLoader.parseColor( value );
|
return (color != null) ? color : parseColor( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorUIResource parseColor( String value ) {
|
||||||
|
try {
|
||||||
|
return UIDefaultsLoader.parseColor( value );
|
||||||
|
} catch( IllegalArgumentException ex ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -540,7 +553,7 @@ public class IntelliJTheme
|
|||||||
// radioFocused.svg and radioSelectedFocused.svg
|
// radioFocused.svg and radioSelectedFocused.svg
|
||||||
// use opacity=".65" for the border
|
// use opacity=".65" for the border
|
||||||
// --> add alpha to focused border colors
|
// --> add alpha to focused border colors
|
||||||
String[] focusedBorderColorKeys = new String[] {
|
String[] focusedBorderColorKeys = {
|
||||||
"CheckBox.icon.focusedBorderColor",
|
"CheckBox.icon.focusedBorderColor",
|
||||||
"CheckBox.icon.focusedSelectedBorderColor",
|
"CheckBox.icon.focusedSelectedBorderColor",
|
||||||
"CheckBox.icon[filled].focusedBorderColor",
|
"CheckBox.icon[filled].focusedBorderColor",
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class UIDefaultsLoader
|
|||||||
|
|
||||||
private static int parseColorDepth;
|
private static int parseColorDepth;
|
||||||
|
|
||||||
|
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 void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||||
@@ -105,6 +106,10 @@ class UIDefaultsLoader
|
|||||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// temporary cache system colors while loading defaults,
|
||||||
|
// which avoids that system color getter is invoked multiple times
|
||||||
|
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
|
||||||
|
|
||||||
// load core properties files
|
// load core properties files
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
for( Class<?> lafClass : lafClasses ) {
|
for( Class<?> lafClass : lafClasses ) {
|
||||||
@@ -276,6 +281,9 @@ 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 );
|
||||||
|
|
||||||
|
// clear/disable system color cache
|
||||||
|
systemColorCache = null;
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load properties files.", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load properties files.", ex );
|
||||||
}
|
}
|
||||||
@@ -326,7 +334,7 @@ class UIDefaultsLoader
|
|||||||
if( newValue == null )
|
if( newValue == null )
|
||||||
throw new IllegalArgumentException( "variable '" + value + "' not found" );
|
throw new IllegalArgumentException( "variable '" + value + "' not found" );
|
||||||
|
|
||||||
return newValue;
|
return resolveValueFromUIManager( newValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !value.startsWith( PROPERTY_PREFIX ) )
|
if( !value.startsWith( PROPERTY_PREFIX ) )
|
||||||
@@ -525,14 +533,14 @@ class UIDefaultsLoader
|
|||||||
case STRING: return value;
|
case STRING: return value;
|
||||||
case BOOLEAN: return parseBoolean( value );
|
case BOOLEAN: return parseBoolean( value );
|
||||||
case CHARACTER: return parseCharacter( value );
|
case CHARACTER: return parseCharacter( value );
|
||||||
case INTEGER: return parseInteger( value, true );
|
case INTEGER: return parseInteger( value );
|
||||||
case INTEGERORFLOAT:return parseIntegerOrFloat( value, true );
|
case INTEGERORFLOAT:return parseIntegerOrFloat( value );
|
||||||
case FLOAT: return parseFloat( value, true );
|
case FLOAT: return parseFloat( value );
|
||||||
case BORDER: return parseBorder( value, resolver, addonClassLoaders );
|
case BORDER: return parseBorder( value, resolver, addonClassLoaders );
|
||||||
case ICON: return parseInstance( value, addonClassLoaders );
|
case ICON: return parseInstance( value, addonClassLoaders );
|
||||||
case INSETS: return parseInsets( value );
|
case INSETS: return parseInsets( value );
|
||||||
case DIMENSION: return parseDimension( value );
|
case DIMENSION: return parseDimension( value );
|
||||||
case COLOR: return parseColorOrFunction( value, resolver, true );
|
case COLOR: return parseColorOrFunction( value, resolver );
|
||||||
case FONT: return parseFont( value );
|
case FONT: return parseFont( value );
|
||||||
case SCALEDINTEGER: return parseScaledInteger( value );
|
case SCALEDINTEGER: return parseScaledInteger( value );
|
||||||
case SCALEDFLOAT: return parseScaledFloat( value );
|
case SCALEDFLOAT: return parseScaledFloat( value );
|
||||||
@@ -550,24 +558,34 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
Object color = parseColorOrFunction( value, resolver, false );
|
if( value.startsWith( "#" ) || value.endsWith( ")" ) ) {
|
||||||
if( color != null ) {
|
Object color = parseColorOrFunction( value, resolver );
|
||||||
resultValueType[0] = ValueType.COLOR;
|
resultValueType[0] = (color != null) ? ValueType.COLOR : ValueType.NULL;
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// integer or float
|
||||||
|
char firstChar = value.charAt( 0 );
|
||||||
|
if( (firstChar >= '0' && firstChar <= '9') ||
|
||||||
|
firstChar == '-' || firstChar == '+' || firstChar == '.' )
|
||||||
|
{
|
||||||
// integer
|
// integer
|
||||||
Integer integer = parseInteger( value, false );
|
try {
|
||||||
if( integer != null ) {
|
Integer integer = parseInteger( value );
|
||||||
resultValueType[0] = ValueType.INTEGER;
|
resultValueType[0] = ValueType.INTEGER;
|
||||||
return integer;
|
return integer;
|
||||||
|
} catch( NumberFormatException ex ) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
// float
|
// float
|
||||||
Float f = parseFloat( value, false );
|
try {
|
||||||
if( f != null ) {
|
Float f = parseFloat( value );
|
||||||
resultValueType[0] = ValueType.FLOAT;
|
resultValueType[0] = ValueType.FLOAT;
|
||||||
return f;
|
return f;
|
||||||
|
} catch( NumberFormatException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// string
|
// string
|
||||||
@@ -596,10 +614,10 @@ class UIDefaultsLoader
|
|||||||
List<String> parts = splitFunctionParams( value, ',' );
|
List<String> parts = splitFunctionParams( value, ',' );
|
||||||
Insets insets = parseInsets( value );
|
Insets insets = parseInsets( value );
|
||||||
ColorUIResource lineColor = (parts.size() >= 5)
|
ColorUIResource lineColor = (parts.size() >= 5)
|
||||||
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
|
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver )
|
||||||
: null;
|
: null;
|
||||||
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty()) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty()) ? parseFloat( parts.get( 5 ) ) : 1f;
|
||||||
int arc = (parts.size() >= 7) ? parseInteger( parts.get( 6 ), true ) : 0;
|
int arc = (parts.size() >= 7) ? parseInteger( parts.get( 6 ) ) : 0;
|
||||||
|
|
||||||
return (LazyValue) t -> {
|
return (LazyValue) t -> {
|
||||||
return (lineColor != null)
|
return (lineColor != null)
|
||||||
@@ -674,30 +692,24 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseColorOrFunction( String value, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorOrFunction( String value, Function<String, String> resolver ) {
|
||||||
if( value.endsWith( ")" ) )
|
if( value.endsWith( ")" ) )
|
||||||
return parseColorFunctions( value, resolver, reportError );
|
return parseColorFunctions( value, resolver );
|
||||||
|
|
||||||
return parseColor( value, reportError );
|
return parseColor( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a hex color in {@code #RGB}, {@code #RGBA}, {@code #RRGGBB} or {@code #RRGGBBAA}
|
||||||
|
* format and returns it as color object.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
static ColorUIResource parseColor( String value ) {
|
static ColorUIResource parseColor( String value ) {
|
||||||
return parseColor( value, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ColorUIResource parseColor( String value, boolean reportError ) {
|
|
||||||
try {
|
|
||||||
int rgba = parseColorRGBA( value );
|
int rgba = parseColorRGBA( value );
|
||||||
return ((rgba & 0xff000000) == 0xff000000)
|
return ((rgba & 0xff000000) == 0xff000000)
|
||||||
? new ColorUIResource( rgba )
|
? new ColorUIResource( rgba )
|
||||||
: new ColorUIResource( new Color( rgba, true ) );
|
: new ColorUIResource( new Color( rgba, true ) );
|
||||||
} catch( IllegalArgumentException ex ) {
|
|
||||||
if( reportError )
|
|
||||||
throw new IllegalArgumentException( "invalid color '" + value + "'" );
|
|
||||||
|
|
||||||
// not a color --> ignore
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -710,7 +722,7 @@ class UIDefaultsLoader
|
|||||||
static int parseColorRGBA( String value ) {
|
static int parseColorRGBA( String value ) {
|
||||||
int len = value.length();
|
int len = value.length();
|
||||||
if( (len != 4 && len != 5 && len != 7 && len != 9) || value.charAt( 0 ) != '#' )
|
if( (len != 4 && len != 5 && len != 7 && len != 9) || value.charAt( 0 ) != '#' )
|
||||||
throw new IllegalArgumentException();
|
throw newInvalidColorException( value );
|
||||||
|
|
||||||
// parse hex
|
// parse hex
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@@ -725,7 +737,7 @@ class UIDefaultsLoader
|
|||||||
else if( ch >= 'A' && ch <= 'F' )
|
else if( ch >= 'A' && ch <= 'F' )
|
||||||
digit = ch - 'A' + 10;
|
digit = ch - 'A' + 10;
|
||||||
else
|
else
|
||||||
throw new IllegalArgumentException();
|
throw newInvalidColorException( value );
|
||||||
|
|
||||||
n = (n << 4) | digit;
|
n = (n << 4) | digit;
|
||||||
}
|
}
|
||||||
@@ -744,14 +756,15 @@ class UIDefaultsLoader
|
|||||||
: (((n >> 8) & 0xffffff) | ((n & 0xff) << 24)); // move alpha from lowest to highest byte
|
: (((n >> 8) & 0xffffff) | ((n & 0xff) << 24)); // move alpha from lowest to highest byte
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseColorFunctions( String value, Function<String, String> resolver, boolean reportError ) {
|
private static IllegalArgumentException newInvalidColorException( String value ) {
|
||||||
int paramsStart = value.indexOf( '(' );
|
return new IllegalArgumentException( "invalid color '" + value + "'" );
|
||||||
if( paramsStart < 0 ) {
|
|
||||||
if( reportError )
|
|
||||||
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object parseColorFunctions( String value, Function<String, String> resolver ) {
|
||||||
|
int paramsStart = value.indexOf( '(' );
|
||||||
|
if( paramsStart < 0 )
|
||||||
|
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
|
||||||
|
|
||||||
String function = StringUtils.substringTrimmed( value, 0, paramsStart );
|
String function = StringUtils.substringTrimmed( value, 0, paramsStart );
|
||||||
List<String> params = splitFunctionParams( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
|
List<String> params = splitFunctionParams( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
|
||||||
if( params.isEmpty() )
|
if( params.isEmpty() )
|
||||||
@@ -763,28 +776,29 @@ class UIDefaultsLoader
|
|||||||
parseColorDepth++;
|
parseColorDepth++;
|
||||||
try {
|
try {
|
||||||
switch( function ) {
|
switch( function ) {
|
||||||
case "if": return parseColorIf( value, params, resolver, reportError );
|
case "if": return parseColorIf( value, params, resolver );
|
||||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver, reportError );
|
case "systemColor": return parseColorSystemColor( value, params, resolver );
|
||||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver, reportError );
|
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
||||||
|
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
||||||
case "hsl": return parseColorHslOrHsla( false, params );
|
case "hsl": return parseColorHslOrHsla( false, params );
|
||||||
case "hsla": return parseColorHslOrHsla( true, params );
|
case "hsla": return parseColorHslOrHsla( true, params );
|
||||||
case "lighten": return parseColorHSLIncreaseDecrease( 2, true, params, resolver, reportError );
|
case "lighten": return parseColorHSLIncreaseDecrease( 2, true, params, resolver );
|
||||||
case "darken": return parseColorHSLIncreaseDecrease( 2, false, params, resolver, reportError );
|
case "darken": return parseColorHSLIncreaseDecrease( 2, false, params, resolver );
|
||||||
case "saturate": return parseColorHSLIncreaseDecrease( 1, true, params, resolver, reportError );
|
case "saturate": return parseColorHSLIncreaseDecrease( 1, true, params, resolver );
|
||||||
case "desaturate": return parseColorHSLIncreaseDecrease( 1, false, params, resolver, reportError );
|
case "desaturate": return parseColorHSLIncreaseDecrease( 1, false, params, resolver );
|
||||||
case "fadein": return parseColorHSLIncreaseDecrease( 3, true, params, resolver, reportError );
|
case "fadein": return parseColorHSLIncreaseDecrease( 3, true, params, resolver );
|
||||||
case "fadeout": return parseColorHSLIncreaseDecrease( 3, false, params, resolver, reportError );
|
case "fadeout": return parseColorHSLIncreaseDecrease( 3, false, params, resolver );
|
||||||
case "fade": return parseColorFade( params, resolver, reportError );
|
case "fade": return parseColorFade( params, resolver );
|
||||||
case "spin": return parseColorSpin( params, resolver, reportError );
|
case "spin": return parseColorSpin( params, resolver );
|
||||||
case "changeHue": return parseColorChange( 0, params, resolver, reportError );
|
case "changeHue": return parseColorChange( 0, params, resolver );
|
||||||
case "changeSaturation":return parseColorChange( 1, params, resolver, reportError );
|
case "changeSaturation":return parseColorChange( 1, params, resolver );
|
||||||
case "changeLightness": return parseColorChange( 2, params, resolver, reportError );
|
case "changeLightness": return parseColorChange( 2, params, resolver );
|
||||||
case "changeAlpha": return parseColorChange( 3, params, resolver, reportError );
|
case "changeAlpha": return parseColorChange( 3, params, resolver );
|
||||||
case "mix": return parseColorMix( null, params, resolver, reportError );
|
case "mix": return parseColorMix( null, params, resolver );
|
||||||
case "tint": return parseColorMix( "#fff", params, resolver, reportError );
|
case "tint": return parseColorMix( "#fff", params, resolver );
|
||||||
case "shade": return parseColorMix( "#000", params, resolver, reportError );
|
case "shade": return parseColorMix( "#000", params, resolver );
|
||||||
case "contrast": return parseColorContrast( params, resolver, reportError );
|
case "contrast": return parseColorContrast( params, resolver );
|
||||||
case "over": return parseColorOver( params, resolver, reportError );
|
case "over": return parseColorOver( params, resolver );
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
parseColorDepth--;
|
parseColorDepth--;
|
||||||
@@ -799,13 +813,51 @@ class UIDefaultsLoader
|
|||||||
* This "if" function is only used if the "if" is passed as parameter to another
|
* This "if" function is only used if the "if" is passed as parameter to another
|
||||||
* color function. Otherwise, the general "if" function is used.
|
* color function. Otherwise, the general "if" function is used.
|
||||||
*/
|
*/
|
||||||
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver ) {
|
||||||
if( params.size() != 3 )
|
if( params.size() != 3 )
|
||||||
throwMissingParametersException( value );
|
throwMissingParametersException( value );
|
||||||
|
|
||||||
boolean ifCondition = parseCondition( params.get( 0 ), resolver, Collections.emptyList() );
|
boolean ifCondition = parseCondition( params.get( 0 ), resolver, Collections.emptyList() );
|
||||||
String ifValue = params.get( ifCondition ? 1 : 2 );
|
String ifValue = params.get( ifCondition ? 1 : 2 );
|
||||||
return parseColorOrFunction( resolver.apply( ifValue ), resolver, reportError );
|
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syntax: systemColor(name[,defaultValue])
|
||||||
|
* - name: system color name
|
||||||
|
* - defaultValue: default color value used if system color is not available
|
||||||
|
*/
|
||||||
|
private static Object parseColorSystemColor( String value, List<String> params, Function<String, String> resolver ) {
|
||||||
|
if( params.size() < 1 )
|
||||||
|
throwMissingParametersException( value );
|
||||||
|
|
||||||
|
ColorUIResource systemColor = getSystemColor( params.get( 0 ) );
|
||||||
|
if( systemColor != null )
|
||||||
|
return systemColor;
|
||||||
|
|
||||||
|
String defaultValue = (params.size() > 1) ? params.get( 1 ) : "";
|
||||||
|
if( defaultValue.equals( "null" ) || defaultValue.isEmpty() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return parseColorOrFunction( resolver.apply( defaultValue ), resolver );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColorUIResource getSystemColor( String name ) {
|
||||||
|
Function<String, Color> systemColorGetter = FlatLaf.getSystemColorGetter();
|
||||||
|
if( systemColorGetter == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// use containsKey() because value may be null
|
||||||
|
if( systemColorCache != null && systemColorCache.containsKey( name ) )
|
||||||
|
return systemColorCache.get( name );
|
||||||
|
|
||||||
|
Color color = systemColorGetter.apply( name );
|
||||||
|
ColorUIResource uiColor = (color != null) ? new ColorUIResource( color ) : null;
|
||||||
|
|
||||||
|
if( systemColorCache != null )
|
||||||
|
systemColorCache.put( name, uiColor );
|
||||||
|
|
||||||
|
return uiColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -816,7 +868,7 @@ class UIDefaultsLoader
|
|||||||
* - alpha: an integer 0-255 or a percentage 0-100%
|
* - alpha: an integer 0-255 or a percentage 0-100%
|
||||||
*/
|
*/
|
||||||
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params,
|
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params,
|
||||||
Function<String, String> resolver, boolean reportError )
|
Function<String, String> resolver )
|
||||||
{
|
{
|
||||||
if( hasAlpha && params.size() == 2 ) {
|
if( hasAlpha && params.size() == 2 ) {
|
||||||
// syntax rgba(color,alpha), which allows adding alpha to any color
|
// syntax rgba(color,alpha), which allows adding alpha to any color
|
||||||
@@ -825,7 +877,7 @@ class UIDefaultsLoader
|
|||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int alpha = parseInteger( params.get( 1 ), 0, 255, true );
|
int alpha = parseInteger( params.get( 1 ), 0, 255, true );
|
||||||
|
|
||||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver );
|
||||||
return new ColorUIResource( new Color( ((alpha & 0xff) << 24) | (color.getRGB() & 0xffffff), true ) );
|
return new ColorUIResource( new Color( ((alpha & 0xff) << 24) | (color.getRGB() & 0xffffff), true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,7 +917,7 @@ class UIDefaultsLoader
|
|||||||
* - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
|
* - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||||
List<String> params, Function<String, String> resolver, boolean reportError )
|
List<String> params, Function<String, String> resolver )
|
||||||
{
|
{
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parsePercentage( params.get( 1 ) );
|
int amount = parsePercentage( params.get( 1 ) );
|
||||||
@@ -900,7 +952,7 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -909,7 +961,7 @@ class UIDefaultsLoader
|
|||||||
* - amount: percentage 0-100%
|
* - amount: percentage 0-100%
|
||||||
* - options: [derived] [lazy]
|
* - options: [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorFade( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorFade( List<String> params, Function<String, String> resolver ) {
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parsePercentage( params.get( 1 ) );
|
int amount = parsePercentage( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
@@ -934,7 +986,7 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -943,9 +995,9 @@ class UIDefaultsLoader
|
|||||||
* - angle: number of degrees to rotate
|
* - angle: number of degrees to rotate
|
||||||
* - options: [derived]
|
* - options: [derived]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorSpin( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorSpin( List<String> params, Function<String, String> resolver ) {
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parseInteger( params.get( 1 ), true );
|
int amount = parseInteger( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
|
|
||||||
if( params.size() > 2 ) {
|
if( params.size() > 2 ) {
|
||||||
@@ -957,7 +1009,7 @@ class UIDefaultsLoader
|
|||||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
|
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -970,11 +1022,11 @@ class UIDefaultsLoader
|
|||||||
* - options: [derived]
|
* - options: [derived]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorChange( int hslIndex,
|
private static Object parseColorChange( int hslIndex,
|
||||||
List<String> params, Function<String, String> resolver, boolean reportError )
|
List<String> params, Function<String, String> resolver )
|
||||||
{
|
{
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int value = (hslIndex == 0)
|
int value = (hslIndex == 0)
|
||||||
? parseInteger( params.get( 1 ), true )
|
? parseInteger( params.get( 1 ) )
|
||||||
: parsePercentage( params.get( 1 ) );
|
: parsePercentage( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
|
|
||||||
@@ -987,7 +1039,7 @@ class UIDefaultsLoader
|
|||||||
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
|
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -999,7 +1051,7 @@ class UIDefaultsLoader
|
|||||||
* - 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
|
||||||
*/
|
*/
|
||||||
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if( color1Str == null )
|
if( color1Str == null )
|
||||||
color1Str = params.get( i++ );
|
color1Str = params.get( i++ );
|
||||||
@@ -1007,7 +1059,7 @@ class UIDefaultsLoader
|
|||||||
int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
|
int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
|
||||||
|
|
||||||
// parse second color
|
// parse second color
|
||||||
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver, reportError );
|
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver );
|
||||||
if( color2 == null )
|
if( color2 == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1015,7 +1067,7 @@ class UIDefaultsLoader
|
|||||||
ColorFunction function = new ColorFunctions.Mix( color2, weight );
|
ColorFunction function = new ColorFunctions.Mix( color2, weight );
|
||||||
|
|
||||||
// parse first color, apply function and create mixed color
|
// parse first color, apply function and create mixed color
|
||||||
return parseFunctionBaseColor( color1Str, function, false, resolver, reportError );
|
return parseFunctionBaseColor( color1Str, function, false, resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1026,14 +1078,14 @@ class UIDefaultsLoader
|
|||||||
* - threshold: the threshold (in range 0-100%) to specify where the transition
|
* - threshold: the threshold (in range 0-100%) to specify where the transition
|
||||||
* from "dark" to "light" is (default is 43%)
|
* from "dark" to "light" is (default is 43%)
|
||||||
*/
|
*/
|
||||||
private static Object parseColorContrast( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorContrast( List<String> params, Function<String, String> resolver ) {
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
String darkStr = params.get( 1 );
|
String darkStr = params.get( 1 );
|
||||||
String lightStr = params.get( 2 );
|
String lightStr = params.get( 2 );
|
||||||
int threshold = (params.size() > 3) ? parsePercentage( params.get( 3 ) ) : 43;
|
int threshold = (params.size() > 3) ? parsePercentage( params.get( 3 ) ) : 43;
|
||||||
|
|
||||||
// parse color to compare against
|
// parse color to compare against
|
||||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver );
|
||||||
if( color == null )
|
if( color == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1043,7 +1095,7 @@ class UIDefaultsLoader
|
|||||||
: darkStr;
|
: darkStr;
|
||||||
|
|
||||||
// parse dark or light color
|
// parse dark or light color
|
||||||
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError );
|
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1052,12 +1104,12 @@ class UIDefaultsLoader
|
|||||||
* the alpha of this color is used as weight to mix the two colors
|
* the alpha of this color is used as weight to mix the two colors
|
||||||
* - background: a background color (e.g. #f00) or a color function
|
* - background: a background color (e.g. #f00) or a color function
|
||||||
*/
|
*/
|
||||||
private static ColorUIResource parseColorOver( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static ColorUIResource parseColorOver( List<String> params, Function<String, String> resolver ) {
|
||||||
String foregroundStr = params.get( 0 );
|
String foregroundStr = params.get( 0 );
|
||||||
String backgroundStr = params.get( 1 );
|
String backgroundStr = params.get( 1 );
|
||||||
|
|
||||||
// parse foreground color
|
// parse foreground color
|
||||||
ColorUIResource foreground = (ColorUIResource) parseColorOrFunction( resolver.apply( foregroundStr ), resolver, reportError );
|
ColorUIResource foreground = (ColorUIResource) parseColorOrFunction( resolver.apply( foregroundStr ), resolver );
|
||||||
if( foreground == null || foreground.getAlpha() == 255 )
|
if( foreground == null || foreground.getAlpha() == 255 )
|
||||||
return foreground;
|
return foreground;
|
||||||
|
|
||||||
@@ -1065,7 +1117,7 @@ class UIDefaultsLoader
|
|||||||
ColorUIResource foreground2 = new ColorUIResource( foreground.getRGB() );
|
ColorUIResource foreground2 = new ColorUIResource( foreground.getRGB() );
|
||||||
|
|
||||||
// parse background color
|
// parse background color
|
||||||
ColorUIResource background = (ColorUIResource) parseColorOrFunction( resolver.apply( backgroundStr ), resolver, reportError );
|
ColorUIResource background = (ColorUIResource) parseColorOrFunction( resolver.apply( backgroundStr ), resolver );
|
||||||
if( background == null )
|
if( background == null )
|
||||||
return foreground2;
|
return foreground2;
|
||||||
|
|
||||||
@@ -1075,11 +1127,11 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
|
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
|
||||||
boolean derived, Function<String, String> resolver, boolean reportError )
|
boolean derived, Function<String, String> resolver )
|
||||||
{
|
{
|
||||||
// parse base color
|
// parse base color
|
||||||
String resolvedColorStr = resolver.apply( colorStr );
|
String resolvedColorStr = resolver.apply( colorStr );
|
||||||
ColorUIResource baseColor = (ColorUIResource) parseColorOrFunction( resolvedColorStr, resolver, reportError );
|
ColorUIResource baseColor = (ColorUIResource) parseColorOrFunction( resolvedColorStr, resolver );
|
||||||
if( baseColor == null )
|
if( baseColor == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1163,11 +1215,11 @@ class UIDefaultsLoader
|
|||||||
throw new IllegalArgumentException( "size specified more than once in '" + value + "'" );
|
throw new IllegalArgumentException( "size specified more than once in '" + value + "'" );
|
||||||
|
|
||||||
if( firstChar == '+' || firstChar == '-' )
|
if( firstChar == '+' || firstChar == '-' )
|
||||||
relativeSize = parseInteger( param, true );
|
relativeSize = parseInteger( param );
|
||||||
else if( param.endsWith( "%" ) )
|
else if( param.endsWith( "%" ) )
|
||||||
scaleSize = parseInteger( param.substring( 0, param.length() - 1 ), true ) / 100f;
|
scaleSize = parseInteger( param.substring( 0, param.length() - 1 ) ) / 100f;
|
||||||
else
|
else
|
||||||
absoluteSize = parseInteger( param, true );
|
absoluteSize = parseInteger( param );
|
||||||
} else if( firstChar == '$' ) {
|
} else if( firstChar == '$' ) {
|
||||||
// reference to base font
|
// reference to base font
|
||||||
if( baseFontKey != null )
|
if( baseFontKey != null )
|
||||||
@@ -1241,55 +1293,49 @@ class UIDefaultsLoader
|
|||||||
return (max * percent) / 100;
|
return (max * percent) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer integer = parseInteger( value, true );
|
Integer integer = parseInteger( value );
|
||||||
if( integer < min || integer > max )
|
if( integer < min || integer > max )
|
||||||
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
||||||
return integer;
|
return integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer parseInteger( String value, boolean reportError ) {
|
private static Integer parseInteger( String value ) {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt( value );
|
return Integer.parseInt( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
if( reportError )
|
|
||||||
throw new NumberFormatException( "invalid integer '" + value + "'" );
|
throw new NumberFormatException( "invalid integer '" + value + "'" );
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Number parseIntegerOrFloat( String value, boolean reportError ) {
|
private static Number parseIntegerOrFloat( String value ) {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt( value );
|
return Integer.parseInt( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
try {
|
try {
|
||||||
return Float.parseFloat( value );
|
return Float.parseFloat( value );
|
||||||
} catch( NumberFormatException ex2 ) {
|
} catch( NumberFormatException ex2 ) {
|
||||||
if( reportError )
|
|
||||||
throw new NumberFormatException( "invalid integer or float '" + value + "'" );
|
throw new NumberFormatException( "invalid integer or float '" + value + "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Float parseFloat( String value, boolean reportError ) {
|
private static Float parseFloat( String value ) {
|
||||||
try {
|
try {
|
||||||
return Float.parseFloat( value );
|
return Float.parseFloat( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
if( reportError )
|
|
||||||
throw new NumberFormatException( "invalid float '" + value + "'" );
|
throw new NumberFormatException( "invalid float '" + value + "'" );
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledInteger( String value ) {
|
private static ActiveValue parseScaledInteger( String value ) {
|
||||||
int val = parseInteger( value, true );
|
int val = parseInteger( value );
|
||||||
return t -> {
|
return t -> {
|
||||||
return UIScale.scale( val );
|
return UIScale.scale( val );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledFloat( String value ) {
|
private static ActiveValue parseScaledFloat( String value ) {
|
||||||
float val = parseFloat( value, true );
|
float val = parseFloat( value );
|
||||||
return t -> {
|
return t -> {
|
||||||
return UIScale.scale( val );
|
return UIScale.scale( val );
|
||||||
};
|
};
|
||||||
@@ -1344,7 +1390,11 @@ class UIDefaultsLoader
|
|||||||
start = i + 1;
|
start = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strs.add( StringUtils.substringTrimmed( str, start ) );
|
|
||||||
|
// last param
|
||||||
|
String s = StringUtils.substringTrimmed( str, start );
|
||||||
|
if( !s.isEmpty() || !strs.isEmpty() )
|
||||||
|
strs.add( s );
|
||||||
|
|
||||||
return strs;
|
return strs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
@@ -36,6 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatCapsLockIcon
|
public class FlatCapsLockIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatCapsLockIcon() {
|
public FlatCapsLockIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||||
}
|
}
|
||||||
@@ -63,16 +68,22 @@ public class FlatCapsLockIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||||
<rect width="6" height="2" x="5" y="11.5" fill="#FFF"/>
|
<rect width="5" height="2" x="5.5" y="11.5" stroke="#FFF" stroke-linejoin="round"/>
|
||||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
<path stroke="#FFF" stroke-linejoin="round" d="M2.5,7.5 L8,2 L13.5,7.5 L10.5,7.5 L10.5,9.5 L5.5,9.5 L5.5,7.5 L2.5,7.5 Z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
||||||
path.append( new Rectangle2D.Float( 5, 11.5f, 6, 2 ), false );
|
path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false );
|
||||||
path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false );
|
path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath(
|
||||||
|
2.5,7.5, 8,2, 13.5,7.5, 10.5,7.5, 10.5,9.5, 5.5,9.5, 5.5,7.5, 2.5,7.5 ) ) ), false );
|
||||||
|
}
|
||||||
g.fill( path );
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ public class FlatCheckBoxIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Component c, Graphics2D g ) {
|
protected void paintCheckmark( Component c, Graphics2D g ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class FlatCheckBoxMenuItemIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Graphics2D g2 ) {
|
protected void paintCheckmark( Graphics2D g2 ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
@@ -103,9 +102,11 @@ public class FlatClearIcon
|
|||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
g.setColor( clearIconColor );
|
g.setColor( clearIconColor );
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( 5,5, 11,11 ), false );
|
path.moveTo( 5, 5 );
|
||||||
path.append( new Line2D.Float( 5,11, 11,5 ), false );
|
path.lineTo( 11, 11 );
|
||||||
|
path.moveTo( 5, 11 );
|
||||||
|
path.lineTo( 11, 5 );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,21 +39,25 @@ public class FlatFileChooserDetailsViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="2" height="2" x="2" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="7" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="11" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="7" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="11" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 2, 3, 2, 2 );
|
g.fillRoundRect( 2, 3, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 7, 2, 2 );
|
g.fillRoundRect( 2, 6, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 11, 2, 2 );
|
g.fillRoundRect( 2, 9, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 3, 8, 2 );
|
g.fillRoundRect( 2, 12, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 7, 8, 2 );
|
g.fillRoundRect( 6, 3, 8, 1, 1, 1 );
|
||||||
g.fillRect( 6, 11, 8, 2 );
|
g.fillRoundRect( 6, 6, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 9, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 12, 8, 1, 1, 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -39,10 +41,22 @@ public class FlatFileChooserHomeFolderIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="2 8 8 2 14 8 12 8 12 13 9 13 9 10 7 10 7 13 4 13 4 8"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linejoin="round" points="6.5 13 6.5 9.5 9.5 9.5 9.5 13"/>
|
||||||
|
<path stroke="#6E6E6E" d="M3.5,6.5 L3.5,12.5 C3.5,13.0522847 3.94771525,13.5 4.5,13.5 L11.5,13.5 C12.0522847,13.5 12.5,13.0522847 12.5,12.5 L12.5,6.5 L12.5,6.5"/>
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round" points="1.5 8.5 8 2 14.5 8.5"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 12,8, 12,13, 9,13, 9,10, 7,10, 7,13, 4,13, 4,8 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 6.5,13, 6.5,9.5, 9.5,9.5, 9.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 3.5,6.5,
|
||||||
|
3.5,12.5, FlatUIUtils.QUAD_TO, 3.5,13.5, 4.5,13.5,
|
||||||
|
11.5,13.5, FlatUIUtils.QUAD_TO, 12.5,13.5, 12.5,12.5,
|
||||||
|
12.5,6.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 1.5,8.5, 8,2, 14.5,8.5 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,17 +42,20 @@ public class FlatFileChooserListViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="4" height="4" x="3" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="3" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 3, 3, 4, 4 );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fillRect( 3, 9, 4, 4 );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
g.fillRect( 9, 9, 4, 4 );
|
|
||||||
g.fillRect( 9, 3, 4, 4 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileChooserNewFolderIcon
|
public class FlatFileChooserNewFolderIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private final Color greenColor = UIManager.getColor( "Actions.Green" );
|
||||||
|
|
||||||
public FlatFileChooserNewFolderIcon() {
|
public FlatFileChooserNewFolderIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -40,13 +45,20 @@ public class FlatFileChooserNewFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 14 5 14 8 11 8 11 10 9 10 9 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#59A869" d="M14,11 L16,11 L16,13 L14,13 L14,15 L12,15 L12,13 L10,13 L10,11 L12,11 L12,9 L14,9 L14,11 Z"/>
|
<line x1="5.5" x2="10.5" y1="9" y2="9" stroke="#59A869" stroke-linecap="round"/>
|
||||||
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#59A869" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 14,5, 14,8, 11,8, 11,10, 9,10, 9,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 14,11, 16,11, 16,13, 14,13, 14,15, 12,15, 12,13, 10,13, 10,11, 12,11, 12,9, 14,9, 14,11 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
|
g.setColor( greenColor );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 9, 10.5f, 9 ) );
|
||||||
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -44,15 +47,20 @@ public class FlatFileChooserUpFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 9 5 9 9 13 9 13 5 14 5 14 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#389FD6" d="M12,4 L12,8 L10,8 L10,4 L8,4 L11,1 L14,4 L12,4 Z"/>
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#389FD6" stroke-linecap="round"/>
|
||||||
|
<polyline stroke="#389FD6" stroke-linecap="round" stroke-linejoin="round" points="5.5 9 8 6.5 10.5 9"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 9,5, 9,9, 13,9, 13,5, 14,5, 14,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
g.setColor( blueColor );
|
g.setColor( blueColor );
|
||||||
g.fill( FlatUIUtils.createPath( 12,4, 12,8, 10,8, 10,4, 8,4, 11,1, 14,4, 12,4 ) );
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,9, 8,6.5, 10.5,9 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,17 +43,18 @@ public class FlatFileViewComputerIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<path fill="#6E6E6E" d="M2,3 L14,3 L14,11 L2,11 L2,3 Z M4,5 L4,9 L12,9 L12,5 L4,5 Z"/>
|
<rect width="11" height="7" x="2.5" y="3.5" stroke="#6E6E6E" rx="1"/>
|
||||||
<rect width="12" height="2" x="2" y="12" fill="#6E6E6E"/>
|
<line x1="8" x2="8" y1="11" y2="12" stroke="#6E6E6E"/>
|
||||||
|
<line x1="4.5" x2="11.5" y1="12.5" y2="12.5" stroke="#6E6E6E" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 3, 12, 8 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 4, 5, 8, 4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 2, 12, 12, 2 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 3.5f, 11, 7, 2, 2 ) );
|
||||||
|
g.drawLine( 8, 11, 8, 12 );
|
||||||
|
g.draw( new Line2D.Float( 4.5f, 12.5f, 11.5f, 12.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewDirectoryIcon
|
public class FlatFileViewDirectoryIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewDirectoryIcon() {
|
public FlatFileViewDirectoryIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,10 +43,32 @@ public class FlatFileViewDirectoryIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Path2D createFolderPath() {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
return FlatUIUtils.createPath(
|
||||||
|
// bottom-right
|
||||||
|
14.5,13.5-arc, FlatUIUtils.QUAD_TO, 14.5,13.5, 14.5-arc,13.5,
|
||||||
|
// bottom-left
|
||||||
|
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
|
||||||
|
// top-left
|
||||||
|
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
|
||||||
|
// top-mid-left
|
||||||
|
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
|
||||||
|
// top-mid-right
|
||||||
|
8.5,4.5,
|
||||||
|
// top-right
|
||||||
|
14.5-arc,4.5, FlatUIUtils.QUAD_TO, 14.5,4.5, 14.5,4.5+arc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewFileIcon
|
public class FlatFileViewFileIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewFileIcon() {
|
public FlatFileViewFileIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,14 +44,33 @@ public class FlatFileViewFileIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<path stroke="#6E6E6E" d="M4,1.5 L8.8,1.5 L8.8,1.5 L13.5,6.2 L13.5,13 C13.5,13.8284271 12.8284271,14.5 12,14.5 L4,14.5 C3.17157288,14.5 2.5,13.8284271 2.5,13 L2.5,3 C2.5,2.17157288 3.17157288,1.5 4,1.5 Z"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<path stroke="#6E6E6E" d="M8.5,2 L8.5,5 C8.5,5.82842712 9.17157288,6.5 10,6.5 L13,6.5 L13,6.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// top-left
|
||||||
|
2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5,
|
||||||
|
// top-right
|
||||||
|
8.8,1.5, 13.5,6.2,
|
||||||
|
// bottom-right
|
||||||
|
13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5,
|
||||||
|
// bottom-left
|
||||||
|
2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc,
|
||||||
|
FlatUIUtils.CLOSE_PATH,
|
||||||
|
|
||||||
|
FlatUIUtils.MOVE_TO, 8.5,2,
|
||||||
|
8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5,
|
||||||
|
13,6.5 );
|
||||||
|
}
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -40,18 +41,22 @@ public class FlatFileViewFloppyDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<path fill="#6E6E6E" d="M11,14 L11,11 L5,11 L5,14 L2,14 L2,2 L14,2 L14,14 L11,14 Z M4,4 L4,8 L12,8 L12,4 L4,4 Z"/>
|
<path stroke="#6E6E6E" d="M3.5,2.5 L11.5,2.5 L11.5,2.5 L13.5,4.5 L13.5,12.5 C13.5,13.0522847 13.0522847,13.5 12.5,13.5 L3.5,13.5 C2.94771525,13.5 2.5,13.0522847 2.5,12.5 L2.5,3.5 C2.5,2.94771525 2.94771525,2.5 3.5,2.5 Z"/>
|
||||||
<rect width="4" height="2" x="6" y="12" fill="#6E6E6E"/>
|
<polyline stroke="#6E6E6E" points="4.5 13 4.5 9.5 11.5 9.5 11.5 13"/>
|
||||||
|
<polyline stroke="#6E6E6E" points="5.5 3 5.5 5.5 10.5 5.5 10.5 3"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( FlatUIUtils.createPath( 11,14, 11,11, 5,11, 5,14, 2,14, 2,2, 14,2, 14,14, 11,14 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( FlatUIUtils.createPath( 4,4, 4,8, 12,8, 12,4, 4,4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 6, 12, 4, 2 );
|
g.draw( FlatUIUtils.createPath( 3.5,2.5, 11.5,2.5, 11.5,2.5, 13.5,4.5,
|
||||||
|
13.5,12.5, FlatUIUtils.QUAD_TO, 13.5,13.5, 12.5,13.5,
|
||||||
|
3.5,13.5, FlatUIUtils.QUAD_TO, 2.5,13.5, 2.5,12.5,
|
||||||
|
2.5,3.5, FlatUIUtils.QUAD_TO, 2.5,2.5, 3.5,2.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 4.5,13, 4.5,9.5, 11.5,9.5, 11.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,3, 5.5,5.5, 10.5,5.5, 10.5,3 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,14 +42,19 @@ public class FlatFileViewHardDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<path fill="#6E6E6E" fill-rule="evenodd" d="M2,6 L14,6 L14,10 L2,10 L2,6 Z M12,8 L12,9 L13,9 L13,8 L12,8 Z M10,8 L10,9 L11,9 L11,8 L10,8 Z"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<rect width="11" height="5" x="2.5" y="5.5" stroke="#6E6E6E" rx="1"/>
|
||||||
|
<circle cx="11.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
<circle cx="9.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 6, 12, 4 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 12, 8, 1, 1 ), false );
|
|
||||||
path.append( new Rectangle2D.Float( 10, 8, 1, 1 ), false );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 5.5f, 11, 5, 2, 2 ) );
|
||||||
g.fill( path );
|
g.fill( new Ellipse2D.Float( 10.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
|
g.fill( new Ellipse2D.Float( 8.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.*;
|
import static com.formdev.flatlaf.util.UIScale.*;
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -96,7 +98,8 @@ public class FlatHelpButtonIcon
|
|||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
||||||
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
||||||
<path fill="#6E6E6E" d="M10,17 L12,17 L12,15 L10,15 L10,17 Z M11,5 C8.8,5 7,6.8 7,9 L9,9 C9,7.9 9.9,7 11,7 C12.1,7 13,7.9 13,9 C13,11 10,10.75 10,14 L12,14 C12,11.75 15,11.5 15,9 C15,6.8 13.2,5 11,5 Z"/>
|
<path stroke="#6E6E6E" stroke-linecap="round" stroke-width="2" d="M8,8.5 C8.25,7 9.66585007,6 11,6 C12.5,6 14,7 14,8.5 C14,10.5 11,11 11,13"/>
|
||||||
|
<circle cx="11" cy="16" r="1.2" fill="#6E6E6E"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -147,22 +150,19 @@ public class FlatHelpButtonIcon
|
|||||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||||
|
|
||||||
// paint question mark
|
// paint question mark
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 11, 5 );
|
q.moveTo( 8,8.5 );
|
||||||
q.curveTo( 8.8,5, 7,6.8, 7,9 );
|
q.curveTo( 8.25,7, 9.66585007,6, 11,6 );
|
||||||
q.lineTo( 9, 9 );
|
q.curveTo( 12.5,6, 14,7, 14,8.5 );
|
||||||
q.curveTo( 9,7.9, 9.9,7, 11,7 );
|
q.curveTo( 14,10.5, 11,11, 11,13 );
|
||||||
q.curveTo( 12.1,7, 13,7.9, 13,9 );
|
|
||||||
q.curveTo( 13,11, 10,10.75, 10,14 );
|
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
q.lineTo( 12, 14 );
|
g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
q.curveTo( 12,11.75, 15,11.5, 15,9 );
|
|
||||||
q.curveTo( 15,6.8, 13.2,5, 11,5 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
g2.translate( focusWidth, focusWidth );
|
g2.translate( focusWidth, focusWidth );
|
||||||
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
||||||
g2.fill( q );
|
g2.draw( q );
|
||||||
g2.fillRect( 10, 15, 2, 2 );
|
g2.fill( new Ellipse2D.Float( 9.8f, 14.8f, 2.4f, 2.4f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
@@ -58,9 +57,11 @@ public class FlatInternalFrameCloseIcon
|
|||||||
float my = height / 2;
|
float my = height / 2;
|
||||||
float r = 3.25f;
|
float r = 3.25f;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( 1f ) );
|
g.setStroke( new BasicStroke( 1f ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Error" icon for {@link javax.swing.JOptionPane}.
|
* "Error" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
||||||
<rect width="4" height="11" x="14" y="7" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="7" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 7, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Information" icon for {@link javax.swing.JOptionPane}.
|
* "Information" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="11" x="14" y="14" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="13" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="7" fill="#FFF"/>
|
<circle cx="16" cy="9" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 14, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 13, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 7, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Question" icon for {@link javax.swing.JOptionPane}.
|
* "Question" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="4" x="14" y="22" fill="#FFF"/>
|
<circle cx="16" cy="24" r="1.7" fill="#FFF"/>
|
||||||
<path fill="#FFF" d="M14,20 C14,20 18,20 18,20 C18,16 23,16 23,12 C23,8 20,6 16,6 C12,6 9,8 9,12 C9,12 13,12 13,12 C13,10 14,9 16,9 C18,9 19,10 19,12 C19,15 14,15 14,20 Z"/>
|
<path stroke="#FFF" stroke-linecap="round" stroke-width="3" d="M11.5,11.75 C11.75,9.5 13.75,8 16,8 C18.25,8 20.5,9.5 20.5,11.75 C20.5,14.75 16,15.5 16,19"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -53,21 +53,17 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 14, 20 );
|
q.moveTo( 11.5,11.75 );
|
||||||
q.lineTo( 18, 20 );
|
q.curveTo( 11.75,9.5, 13.75,8, 16,8 );
|
||||||
q.curveTo( 18, 16, 23, 16, 23, 12 );
|
q.curveTo( 18.25,8, 20.5,9.5, 20.5,11.75 );
|
||||||
q.curveTo( 23, 8, 20, 6, 16, 6 );
|
q.curveTo( 20.5,14.75, 16,15.5, 16,19 );
|
||||||
q.curveTo( 12, 6, 9, 8, 9, 12 );
|
|
||||||
q.curveTo( 9, 12, 13, 12, 13, 12 );
|
BasicStroke stroke = new BasicStroke( 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER );
|
||||||
q.curveTo( 13, 10, 14, 9, 16, 9 );
|
|
||||||
q.curveTo( 18, 9, 19, 10, 19, 12 );
|
|
||||||
q.curveTo( 19, 15, 14, 15, 14, 20 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 22, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14.3f, 22.3f, 3.4f, 3.4f ), false );
|
||||||
inside.append( q, false );
|
inside.append( stroke.createStrokedShape( q ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,23 +40,24 @@ public class FlatOptionPaneWarningIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#EDA200" points="16 2 31 28 1 28"/>
|
<path fill="#EDA200" d="M17.7364863,3.038851 L30.2901269,25.0077221 C30.8381469,25.966757 30.5049534,27.1884663 29.5459185,27.7364863 C29.2437231,27.9091694 28.9016945,28 28.5536406,28 L3.44635936,28 C2.34178986,28 1.44635936,27.1045695 1.44635936,26 C1.44635936,25.6519461 1.53718999,25.3099175 1.70987307,25.0077221 L14.2635137,3.038851 C14.8115337,2.0798161 16.033243,1.74662265 16.9922779,2.29464259 C17.3023404,2.47182119 17.5593077,2.72878844 17.7364863,3.038851 Z"/>
|
||||||
<rect width="4" height="8" x="14" y="10" fill="#FFF"/>
|
<rect width="4" height="11" x="14" y="8" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createOutside() {
|
protected Shape createOutside() {
|
||||||
return FlatUIUtils.createPath( 16,2, 31,28, 1,28 );
|
return FlatUIUtils.createRoundTrianglePath( 16,0, 32,28, 0,28, 4 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 10, 4, 8 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 8, 4, 11, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public class FlatSearchIcon
|
|||||||
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
||||||
|
|
||||||
private final boolean ignoreButtonState;
|
private final boolean ignoreButtonState;
|
||||||
|
private Area area;
|
||||||
|
|
||||||
public FlatSearchIcon() {
|
public FlatSearchIcon() {
|
||||||
this( false );
|
this( false );
|
||||||
@@ -89,9 +90,11 @@ public class FlatSearchIcon
|
|||||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||||
|
|
||||||
// paint magnifier
|
// paint magnifier
|
||||||
Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
if( area == null ) {
|
||||||
|
area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
||||||
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
|
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
|
||||||
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
|
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
|
||||||
|
}
|
||||||
g.fill( area );
|
g.fill( area );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
@@ -100,9 +99,11 @@ public class FlatTabbedPaneCloseIcon
|
|||||||
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -31,6 +32,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeClosedIcon
|
public class FlatTreeClosedIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeClosedIcon() {
|
public FlatTreeClosedIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
||||||
}
|
}
|
||||||
@@ -41,10 +44,14 @@ public class FlatTreeClosedIcon
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = FlatFileViewDirectoryIcon.createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.JTree;
|
import javax.swing.JTree;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -39,6 +41,7 @@ public class FlatTreeCollapsedIcon
|
|||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
private final boolean chevron;
|
private final boolean chevron;
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeCollapsedIcon() {
|
public FlatTreeCollapsedIcon() {
|
||||||
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
||||||
@@ -59,10 +62,15 @@ public class FlatTreeCollapsedIcon
|
|||||||
|
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
g.fill( FlatUIUtils.createPath( 3,1, 3,2.5, 6,5.5, 3,8.5, 3,10, 4.5,10, 9,5.5, 4.5,1 ) );
|
g.setStroke( new BasicStroke( 1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER ) );
|
||||||
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( false, 3.5,1.5, 7.5,5.5, 3.5,9.5 );
|
||||||
|
g.draw( path );
|
||||||
} else {
|
} else {
|
||||||
// triangle arrow
|
// triangle arrow
|
||||||
g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) );
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 );
|
||||||
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -42,13 +46,22 @@ public class FlatTreeLeafIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<rect width="11" height="13" x="2.5" y="1.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<line x1="5.5" x2="10.5" y1="5.5" y2="5.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="8" y2="8" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="10.5" y2="10.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 1.5f, 11, 13, 3, 3 ) );
|
||||||
|
|
||||||
|
g.setColor( ColorFunctions.fade( g.getColor(), 0.6f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 5.5f, 10.5f, 5.5f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 8, 10.5f, 8 ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 10.5f, 10.5f, 10.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeOpenIcon
|
public class FlatTreeOpenIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeOpenIcon() {
|
public FlatTreeOpenIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
||||||
}
|
}
|
||||||
@@ -41,14 +46,38 @@ public class FlatTreeOpenIcon
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<path fill="none" stroke="#6E6E6E" d="M2,13.5 L4.11538462,8.42307692 C4.34828895,7.86410651 4.89444872,7.5 5.5,7.5 L14.75,7.5 C15.0261424,7.5 15.25,7.72385763 15.25,8 C15.25,8.06601301 15.2369281,8.13137261 15.2115385,8.19230769 L13.3846154,12.5769231 C13.151711,13.1358935 12.6055513,13.5 12,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L12,4.5 C12.8284271,4.5 13.5,5.17157288 13.5,6 L13.5,6.5 L13.5,6.5"/>
|
||||||
<polygon fill="#6E6E6E" points="1 2 6 2 8 4 14 4 14 6 3.5 6 1 11"/>
|
|
||||||
<polygon fill="#6E6E6E" points="4 7 16 7 13 13 1 13"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 14,4, 14,6, 3.5,6, 1,11 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 4,7, 16,7, 13,13, 1,13 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// bottom-left of opend part
|
||||||
|
2,13.5,
|
||||||
|
// top-left of opend part
|
||||||
|
FlatUIUtils.ROUNDED, 4.5,7.5, arc,
|
||||||
|
// top-right of opend part
|
||||||
|
FlatUIUtils.ROUNDED, 15.5,7.5, arc2,
|
||||||
|
|
||||||
|
// bottom-right
|
||||||
|
FlatUIUtils.ROUNDED, 13,13.5, arc,
|
||||||
|
// bottom-left
|
||||||
|
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
|
||||||
|
// top-left
|
||||||
|
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
|
||||||
|
// top-mid-left
|
||||||
|
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
|
||||||
|
// top-mid-right
|
||||||
|
8.5,4.5,
|
||||||
|
// top-right
|
||||||
|
13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc,
|
||||||
|
13.5,6.5 );
|
||||||
|
}
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
@@ -57,9 +56,11 @@ public class FlatWindowCloseIcon
|
|||||||
int iy2 = iy + iwh - 1;
|
int iy2 = iy + iwh - 1;
|
||||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
path.moveTo( ix, iy );
|
||||||
path.append( new Line2D.Float( ix, iy2, ix2, iy ), false );
|
path.lineTo( ix2, iy2 );
|
||||||
|
path.moveTo( ix, iy2 );
|
||||||
|
path.lineTo( ix2, iy );
|
||||||
g.setStroke( new BasicStroke( thickness ) );
|
g.setStroke( new BasicStroke( thickness ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS dark look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacDarkLaf.properties},
|
||||||
|
* {@code FlatDarkLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacDarkLaf
|
||||||
|
extends FlatDarkLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Dark";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacDarkLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacDarkLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Dark Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS light look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacLightLaf.properties},
|
||||||
|
* {@code FlatLightLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacLightLaf
|
||||||
|
extends FlatLightLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Light";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacLightLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacLightLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Light Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,8 +49,10 @@ public class FlatArrowButton
|
|||||||
protected Color pressedBackground;
|
protected Color pressedBackground;
|
||||||
|
|
||||||
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
||||||
|
private float arrowThickness = 1;
|
||||||
private float xOffset = 0;
|
private float xOffset = 0;
|
||||||
private float yOffset = 0;
|
private float yOffset = 0;
|
||||||
|
private boolean roundBorderAutoXOffset = true;
|
||||||
|
|
||||||
private boolean hover;
|
private boolean hover;
|
||||||
private boolean pressed;
|
private boolean pressed;
|
||||||
@@ -121,6 +123,16 @@ public class FlatArrowButton
|
|||||||
this.arrowWidth = arrowWidth;
|
this.arrowWidth = arrowWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setArrowThickness( float arrowThickness ) {
|
||||||
|
this.arrowThickness = arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isHover() {
|
protected boolean isHover() {
|
||||||
return hover;
|
return hover;
|
||||||
}
|
}
|
||||||
@@ -145,6 +157,16 @@ public class FlatArrowButton
|
|||||||
this.yOffset = yOffset;
|
this.yOffset = yOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
|
||||||
|
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
protected Color deriveBackground( Color background ) {
|
protected Color deriveBackground( Color background ) {
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@@ -208,14 +230,17 @@ public class FlatArrowButton
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintArrow( Graphics2D g ) {
|
protected void paintArrow( Graphics2D g ) {
|
||||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
// move arrow for round borders
|
// move arrow for round borders
|
||||||
|
if( isRoundBorderAutoXOffset() ) {
|
||||||
Container parent = getParent();
|
Container parent = getParent();
|
||||||
|
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||||
|
}
|
||||||
|
|
||||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, getArrowWidth(), getXOffset(), getYOffset() );
|
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
|||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
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.Font;
|
import java.awt.Font;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@@ -45,8 +46,10 @@ 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.plaf.ButtonUI;
|
import javax.swing.plaf.ButtonUI;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.ToolBarUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
@@ -797,5 +800,20 @@ public class FlatButtonUI
|
|||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
FlatButtonUI.this.propertyChange( b, e );
|
FlatButtonUI.this.propertyChange( b, e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
super.stateChanged( e );
|
||||||
|
|
||||||
|
// if button is in toolbar, repaint button groups
|
||||||
|
AbstractButton b = (AbstractButton) e.getSource();
|
||||||
|
Container parent = b.getParent();
|
||||||
|
if( parent instanceof JToolBar ) {
|
||||||
|
JToolBar toolBar = (JToolBar) parent;
|
||||||
|
ToolBarUI ui = toolBar.getUI();
|
||||||
|
if( ui instanceof FlatToolBarUI )
|
||||||
|
((FlatToolBarUI)ui).repaintButtonGroup( b );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ import javax.swing.plaf.basic.BasicComboBoxUI;
|
|||||||
import javax.swing.plaf.basic.BasicComboPopup;
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
import javax.swing.plaf.basic.ComboPopup;
|
import javax.swing.plaf.basic.ComboPopup;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
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;
|
||||||
@@ -99,7 +100,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault ComboBox.minimumWidth int
|
* @uiDefault ComboBox.minimumWidth int
|
||||||
* @uiDefault ComboBox.editorColumns int
|
* @uiDefault ComboBox.editorColumns int
|
||||||
* @uiDefault ComboBox.maximumRowCount int
|
* @uiDefault ComboBox.maximumRowCount int
|
||||||
* @uiDefault ComboBox.buttonStyle String auto (default), button or none
|
* @uiDefault ComboBox.buttonStyle String auto (default), button, mac or none
|
||||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
* @uiDefault Component.isIntelliJTheme boolean
|
||||||
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
||||||
@@ -117,6 +118,9 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault ComboBox.buttonHoverArrowColor Color
|
* @uiDefault ComboBox.buttonHoverArrowColor Color
|
||||||
* @uiDefault ComboBox.buttonPressedArrowColor Color
|
* @uiDefault ComboBox.buttonPressedArrowColor Color
|
||||||
* @uiDefault ComboBox.popupBackground Color optional
|
* @uiDefault ComboBox.popupBackground Color optional
|
||||||
|
* @uiDefault ComboBox.popupInsets Insets
|
||||||
|
* @uiDefault ComboBox.selectionInsets Insets
|
||||||
|
* @uiDefault ComboBox.selectionArc int
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
@@ -150,6 +154,9 @@ public class FlatComboBoxUI
|
|||||||
@Styleable protected Color buttonPressedArrowColor;
|
@Styleable protected Color buttonPressedArrowColor;
|
||||||
|
|
||||||
@Styleable protected Color popupBackground;
|
@Styleable protected Color popupBackground;
|
||||||
|
/** @since 3 */ @Styleable protected Insets popupInsets;
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc;
|
||||||
|
|
||||||
private MouseListener hoverListener;
|
private MouseListener hoverListener;
|
||||||
protected boolean hover;
|
protected boolean hover;
|
||||||
@@ -253,6 +260,9 @@ public class FlatComboBoxUI
|
|||||||
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
|
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
|
||||||
|
|
||||||
popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
|
popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
|
||||||
|
popupInsets = UIManager.getInsets( "ComboBox.popupInsets" );
|
||||||
|
selectionInsets = UIManager.getInsets( "ComboBox.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "ComboBox.selectionArc" );
|
||||||
|
|
||||||
// set maximumRowCount
|
// set maximumRowCount
|
||||||
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
|
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
|
||||||
@@ -559,7 +569,9 @@ public class FlatComboBoxUI
|
|||||||
int height = c.getHeight();
|
int height = c.getHeight();
|
||||||
int arrowX = arrowButton.getX();
|
int arrowX = arrowButton.getX();
|
||||||
int arrowWidth = arrowButton.getWidth();
|
int arrowWidth = arrowButton.getWidth();
|
||||||
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) && !"none".equals( buttonStyle );
|
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) &&
|
||||||
|
!"none".equals( buttonStyle ) &&
|
||||||
|
!isMacStyle();
|
||||||
boolean enabled = comboBox.isEnabled();
|
boolean enabled = comboBox.isEnabled();
|
||||||
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
|
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
|
||||||
|
|
||||||
@@ -577,6 +589,13 @@ public class FlatComboBoxUI
|
|||||||
: buttonBackground;
|
: buttonBackground;
|
||||||
if( buttonColor != null ) {
|
if( buttonColor != null ) {
|
||||||
g2.setColor( buttonColor );
|
g2.setColor( buttonColor );
|
||||||
|
if( isMacStyle() ) {
|
||||||
|
Insets insets = comboBox.getInsets();
|
||||||
|
int gap = scale( 2 );
|
||||||
|
FlatUIUtils.paintComponentBackground( g2, arrowX + gap, insets.top + gap,
|
||||||
|
arrowWidth - (gap * 2), height - insets.top - insets.bottom - (gap * 2),
|
||||||
|
0, arc - focusWidth );
|
||||||
|
} else {
|
||||||
Shape oldClip = g2.getClip();
|
Shape oldClip = g2.getClip();
|
||||||
if( isLeftToRight )
|
if( isLeftToRight )
|
||||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||||
@@ -586,6 +605,7 @@ public class FlatComboBoxUI
|
|||||||
g2.setClip( oldClip );
|
g2.setClip( oldClip );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// paint vertical line between value and arrow button
|
// paint vertical line between value and arrow button
|
||||||
if( paintButton ) {
|
if( paintButton ) {
|
||||||
@@ -722,6 +742,10 @@ public class FlatComboBoxUI
|
|||||||
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
|
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMacStyle() {
|
||||||
|
return "mac".equals( buttonStyle );
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 1.3 */
|
/** @since 1.3 */
|
||||||
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
|
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
|
||||||
if( comboBox.isEditable() ) {
|
if( comboBox.isEditable() ) {
|
||||||
@@ -756,6 +780,21 @@ public class FlatComboBoxUI
|
|||||||
buttonHoverArrowColor, null, buttonPressedArrowColor, null );
|
buttonHoverArrowColor, null, buttonPressedArrowColor, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getArrowWidth() {
|
||||||
|
return isMacStyle() ? (getWidth() % 2 == 0 ? 6 : 7) : super.getArrowWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return isMacStyle() ? 1.5f : super.getArrowThickness();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return isMacStyle() ? false : super.isRoundBorderAutoXOffset();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isHover() {
|
protected boolean isHover() {
|
||||||
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
||||||
@@ -773,6 +812,20 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
return super.getArrowColor();
|
return super.getArrowColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintArrow( Graphics2D g ) {
|
||||||
|
if( isMacStyle() && !comboBox.isEditable() ) {
|
||||||
|
// for style "mac", paint up and down arrows if combobox is not editable
|
||||||
|
int height = getHeight();
|
||||||
|
int h = Math.round( height / 2f );
|
||||||
|
FlatUIUtils.paintArrow( g, 0, 0, getWidth(), h, SwingConstants.NORTH, chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() + 1.25f );
|
||||||
|
FlatUIUtils.paintArrow( g, 0, height - h, getWidth(), h, SwingConstants.SOUTH, chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() - 1.25f );
|
||||||
|
} else
|
||||||
|
super.paintArrow( g );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatComboPopup -----------------------------------------------
|
//---- class FlatComboPopup -----------------------------------------------
|
||||||
@@ -807,12 +860,19 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for style "mac", add width of "checked item" icon
|
||||||
|
boolean isPopupOverComboBox = isPopupOverComboBox();
|
||||||
|
int selectedIndex = -1;
|
||||||
|
if( isPopupOverComboBox && (selectedIndex = comboBox.getSelectedIndex()) >= 0 )
|
||||||
|
displayWidth += MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( CellPaddingBorder.MAC_STYLE_GAP );
|
||||||
|
|
||||||
// add width of vertical scroll bar
|
// add width of vertical scroll bar
|
||||||
JScrollBar verticalScrollBar = scroller.getVerticalScrollBar();
|
JScrollBar verticalScrollBar = scroller.getVerticalScrollBar();
|
||||||
if( verticalScrollBar != null )
|
if( verticalScrollBar != null )
|
||||||
displayWidth += verticalScrollBar.getPreferredSize().width;
|
displayWidth += verticalScrollBar.getPreferredSize().width;
|
||||||
|
|
||||||
// make popup wider if necessary
|
// make popup wider if necessary
|
||||||
|
int pw0 = pw;
|
||||||
if( displayWidth > pw ) {
|
if( displayWidth > pw ) {
|
||||||
// limit popup width to screen width
|
// limit popup width to screen width
|
||||||
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
||||||
@@ -832,6 +892,30 @@ public class FlatComboBoxUI
|
|||||||
px -= diff;
|
px -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for style "mac", place popup over combobox
|
||||||
|
Rectangle cellBounds;
|
||||||
|
if( isPopupOverComboBox && selectedIndex >= 0 &&
|
||||||
|
(cellBounds = list.getCellBounds( 0, 0 )) != null )
|
||||||
|
{
|
||||||
|
Insets comboBoxInsets = comboBox.getInsets();
|
||||||
|
Insets listInsets = list.getInsets();
|
||||||
|
Insets popupInsets = getInsets();
|
||||||
|
|
||||||
|
// position popup so that selected item is at same Y position as combobox
|
||||||
|
py -= (cellBounds.height * (selectedIndex + 1)) + comboBoxInsets.top + listInsets.top + popupInsets.top;
|
||||||
|
|
||||||
|
// position popup slightly to the left so that a small part of the right side of the combobox stays visible
|
||||||
|
int offset = Math.min( pw - pw0, MacCheckedItemIcon.INSTANCE.getIconWidth() ) + scale( 4 );
|
||||||
|
if( comboBox.getComponentOrientation().isLeftToRight() )
|
||||||
|
px -= offset + comboBoxInsets.right + listInsets.right;
|
||||||
|
else
|
||||||
|
px += offset + comboBoxInsets.left + listInsets.left;
|
||||||
|
|
||||||
|
// not invoking super.computePopupBounds() here to let
|
||||||
|
// JPopupMenu.adjustPopupLocationToFitScreen() fix the location if necessary
|
||||||
|
return new Rectangle( px, py, pw, ph );
|
||||||
|
}
|
||||||
|
|
||||||
return super.computePopupBounds( px, py, pw, ph );
|
return super.computePopupBounds( px, py, pw, ph );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -848,11 +932,6 @@ public class FlatComboBoxUI
|
|||||||
Border border = UIManager.getBorder( "PopupMenu.border" );
|
Border border = UIManager.getBorder( "PopupMenu.border" );
|
||||||
if( border != null )
|
if( border != null )
|
||||||
setBorder( FlatUIUtils.nonUIResource( border ) );
|
setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureList() {
|
|
||||||
super.configureList();
|
|
||||||
|
|
||||||
list.setCellRenderer( new PopupListCellRenderer() );
|
list.setCellRenderer( new PopupListCellRenderer() );
|
||||||
updateStyle();
|
updateStyle();
|
||||||
@@ -866,6 +945,15 @@ public class FlatComboBoxUI
|
|||||||
// use non-UIResource to avoid that it is overwritten when making
|
// use non-UIResource to avoid that it is overwritten when making
|
||||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||||
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
||||||
|
|
||||||
|
scroller.setViewportBorder( (popupInsets != null) ? new FlatEmptyBorder( popupInsets ) : null );
|
||||||
|
scroller.setOpaque( false );
|
||||||
|
|
||||||
|
if( list.getUI() instanceof FlatListUI ) {
|
||||||
|
FlatListUI ui = (FlatListUI) list.getUI();
|
||||||
|
ui.selectionInsets = selectionInsets;
|
||||||
|
ui.selectionArc = selectionArc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -907,6 +995,15 @@ public class FlatComboBoxUI
|
|||||||
paddingBorder.uninstall();
|
paddingBorder.uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPopupOverComboBox() {
|
||||||
|
return isMacStyle() &&
|
||||||
|
!comboBox.isEditable() &&
|
||||||
|
comboBox.getItemCount() > 0 &&
|
||||||
|
comboBox.getItemCount() <= comboBox.getMaximumRowCount() &&
|
||||||
|
// for compatibility with Aqua Laf
|
||||||
|
!clientPropertyBoolean( comboBox, "JComboBox.isPopDown", false );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class PopupListCellRenderer -----
|
//---- class PopupListCellRenderer -----
|
||||||
|
|
||||||
private class PopupListCellRenderer
|
private class PopupListCellRenderer
|
||||||
@@ -924,6 +1021,13 @@ public class FlatComboBoxUI
|
|||||||
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
||||||
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||||
|
|
||||||
|
// style "mac"
|
||||||
|
if( isPopupOverComboBox() && c instanceof JComponent ) {
|
||||||
|
int selectedIndex = comboBox.getSelectedIndex();
|
||||||
|
((JComponent)c).putClientProperty( CellPaddingBorder.KEY_MAC_STYLE_HINT,
|
||||||
|
(selectedIndex >= 0) ? (index == selectedIndex) : null );
|
||||||
|
}
|
||||||
|
|
||||||
paddingBorder.install( c, Math.round( FlatUIUtils.getBorderFocusWidth( comboBox ) ) );
|
paddingBorder.install( c, Math.round( FlatUIUtils.getBorderFocusWidth( comboBox ) ) );
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
@@ -940,10 +1044,16 @@ public class FlatComboBoxUI
|
|||||||
* which vertically aligns text in popup list with text in combobox.
|
* which vertically aligns text in popup list with text in combobox.
|
||||||
* <p>
|
* <p>
|
||||||
* The renderer border is painted on the outer side of this border.
|
* The renderer border is painted on the outer side of this border.
|
||||||
|
* <p>
|
||||||
|
* For button style "mac", also used to increase insets on left side for
|
||||||
|
* "checked item" icon and to paint "checked item" icon for selected combobox item.
|
||||||
*/
|
*/
|
||||||
private static class CellPaddingBorder
|
private static class CellPaddingBorder
|
||||||
extends AbstractBorder
|
extends AbstractBorder
|
||||||
{
|
{
|
||||||
|
static final String KEY_MAC_STYLE_HINT = "FlatLaf.internal.FlatComboBoxUI.macStyleHint";
|
||||||
|
static final int MAC_STYLE_GAP = 4;
|
||||||
|
|
||||||
private Insets padding;
|
private Insets padding;
|
||||||
private JComponent rendererComponent;
|
private JComponent rendererComponent;
|
||||||
private Border rendererBorder;
|
private Border rendererBorder;
|
||||||
@@ -993,6 +1103,8 @@ public class FlatComboBoxUI
|
|||||||
if( rendererComponent == null )
|
if( rendererComponent == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
rendererComponent.putClientProperty( KEY_MAC_STYLE_HINT, null );
|
||||||
|
|
||||||
if( rendererComponent.getBorder() == this )
|
if( rendererComponent.getBorder() == this )
|
||||||
rendererComponent.setBorder( rendererBorder );
|
rendererComponent.setBorder( rendererBorder );
|
||||||
rendererComponent = null;
|
rendererComponent = null;
|
||||||
@@ -1020,6 +1132,18 @@ public class FlatComboBoxUI
|
|||||||
insets.left += focusWidth;
|
insets.left += focusWidth;
|
||||||
insets.right += focusWidth;
|
insets.right += focusWidth;
|
||||||
|
|
||||||
|
// style "mac"
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||||
|
if( macStyleHint != null ) {
|
||||||
|
int indent = MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( MAC_STYLE_GAP );
|
||||||
|
if( c.getComponentOrientation().isLeftToRight() )
|
||||||
|
insets.left += indent;
|
||||||
|
else
|
||||||
|
insets.right += indent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return insets;
|
return insets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,6 +1151,35 @@ public class FlatComboBoxUI
|
|||||||
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( rendererBorder != null )
|
if( rendererBorder != null )
|
||||||
rendererBorder.paintBorder( c, g, x, y, width, height );
|
rendererBorder.paintBorder( c, g, x, y, width, height );
|
||||||
|
|
||||||
|
// style "mac"
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||||
|
if( macStyleHint == Boolean.TRUE ) {
|
||||||
|
// paint "checked item" icon
|
||||||
|
int ix = c.getComponentOrientation().isLeftToRight()
|
||||||
|
? x + scale( padding.left )
|
||||||
|
: x + width - scale( padding.right ) - MacCheckedItemIcon.INSTANCE.getIconWidth();
|
||||||
|
MacCheckedItemIcon.INSTANCE.paintIcon( c, g, ix, y + ((height - MacCheckedItemIcon.INSTANCE.getIconHeight()) / 2) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class MacCheckedItemIcon -------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use for style "mac" to mark checked item.
|
||||||
|
*/
|
||||||
|
private static class MacCheckedItemIcon
|
||||||
|
extends FlatCheckBoxMenuItemIcon
|
||||||
|
{
|
||||||
|
static MacCheckedItemIcon INSTANCE = new MacCheckedItemIcon();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
|
g2.setColor( c.getForeground() );
|
||||||
|
paintCheckmark( g2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -243,11 +243,13 @@ public class FlatFileChooserUI
|
|||||||
borderLayout.setHgap( 8 );
|
borderLayout.setHgap( 8 );
|
||||||
|
|
||||||
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
||||||
|
Component lineEnd = borderLayout.getLayoutComponent( BorderLayout.LINE_END );
|
||||||
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
||||||
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
||||||
if( north != null && center != null && south != null ) {
|
if( north != null && lineEnd != null && center != null && south != null ) {
|
||||||
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
||||||
p.add( north, BorderLayout.NORTH );
|
p.add( north, BorderLayout.NORTH );
|
||||||
|
p.add( lineEnd, BorderLayout.LINE_END );
|
||||||
p.add( center, BorderLayout.CENTER );
|
p.add( center, BorderLayout.CENTER );
|
||||||
p.add( south, BorderLayout.SOUTH );
|
p.add( south, BorderLayout.SOUTH );
|
||||||
fc.add( p, BorderLayout.CENTER );
|
fc.add( p, BorderLayout.CENTER );
|
||||||
|
|||||||
@@ -17,20 +17,34 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.ListCellRenderer;
|
||||||
|
import javax.swing.ListModel;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||||
import javax.swing.plaf.basic.BasicListUI;
|
import javax.swing.plaf.basic.BasicListUI;
|
||||||
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.Graphics2DProxy;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JList}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JList}.
|
||||||
@@ -59,6 +73,8 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
*
|
*
|
||||||
* @uiDefault List.selectionInactiveBackground Color
|
* @uiDefault List.selectionInactiveBackground Color
|
||||||
* @uiDefault List.selectionInactiveForeground Color
|
* @uiDefault List.selectionInactiveForeground Color
|
||||||
|
* @uiDefault List.selectionInsets Insets
|
||||||
|
* @uiDefault List.selectionArc int
|
||||||
*
|
*
|
||||||
* <!-- FlatListCellBorder -->
|
* <!-- FlatListCellBorder -->
|
||||||
*
|
*
|
||||||
@@ -76,6 +92,8 @@ 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 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc;
|
||||||
|
|
||||||
// for FlatListCellBorder
|
// for FlatListCellBorder
|
||||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||||
@@ -110,6 +128,8 @@ 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" );
|
||||||
|
selectionInsets = UIManager.getInsets( "List.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "List.selectionArc" );
|
||||||
|
|
||||||
toggleSelectionColors();
|
toggleSelectionColors();
|
||||||
}
|
}
|
||||||
@@ -168,6 +188,29 @@ public class FlatListUI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ListSelectionListener createListSelectionListener() {
|
||||||
|
ListSelectionListener superListener = super.createListSelectionListener();
|
||||||
|
return e -> {
|
||||||
|
superListener.valueChanged( e );
|
||||||
|
|
||||||
|
// for united rounded selection, repaint parts of the rows/columns that adjoin to the changed rows/columns
|
||||||
|
if( useUnitedRoundedSelection( true, true ) &&
|
||||||
|
!list.isSelectionEmpty() &&
|
||||||
|
(list.getMaxSelectionIndex() - list.getMinSelectionIndex()) >= 1 )
|
||||||
|
{
|
||||||
|
int size = list.getModel().getSize();
|
||||||
|
int firstIndex = Math.min( Math.max( e.getFirstIndex(), 0 ), size - 1 );
|
||||||
|
int lastIndex = Math.min( Math.max( e.getLastIndex(), 0 ), size - 1 );
|
||||||
|
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
||||||
|
if( r != null ) {
|
||||||
|
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) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void installStyle() {
|
protected void installStyle() {
|
||||||
try {
|
try {
|
||||||
@@ -247,4 +290,165 @@ public class FlatListUI
|
|||||||
list.setSelectionForeground( selectionInactiveForeground );
|
list.setSelectionForeground( selectionInactiveForeground );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "rawtypes" )
|
||||||
|
@Override
|
||||||
|
protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRenderer cellRenderer,
|
||||||
|
ListModel dataModel, ListSelectionModel selModel, int leadIndex )
|
||||||
|
{
|
||||||
|
boolean isSelected = selModel.isSelectedIndex( row );
|
||||||
|
|
||||||
|
// get renderer component
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
|
||||||
|
dataModel.getElementAt( row ), row, isSelected,
|
||||||
|
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );
|
||||||
|
|
||||||
|
//
|
||||||
|
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
|
||||||
|
int cx, cw;
|
||||||
|
if( isFileList ) {
|
||||||
|
// see BasicListUI.paintCell()
|
||||||
|
cw = Math.min( rowBounds.width, rendererComponent.getPreferredSize().width + 4 );
|
||||||
|
cx = list.getComponentOrientation().isLeftToRight()
|
||||||
|
? rowBounds.x
|
||||||
|
: rowBounds.x + (rowBounds.width - cw);
|
||||||
|
} else {
|
||||||
|
cx = rowBounds.x;
|
||||||
|
cw = rowBounds.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rounded selection or selection insets
|
||||||
|
if( isSelected &&
|
||||||
|
!isFileList && // rounded selection is not supported for file list
|
||||||
|
(rendererComponent instanceof DefaultListCellRenderer ||
|
||||||
|
rendererComponent instanceof BasicComboBoxRenderer) &&
|
||||||
|
(selectionArc > 0 ||
|
||||||
|
(selectionInsets != null &&
|
||||||
|
(selectionInsets.top != 0 || selectionInsets.left != 0 || selectionInsets.bottom != 0 || selectionInsets.right != 0))) )
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// To solve this, a graphics proxy is used that paints rounded selection
|
||||||
|
// if row is selected and the renderer wants to fill the background.
|
||||||
|
class RoundedSelectionGraphics extends Graphics2DProxy {
|
||||||
|
// 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 ) {
|
||||||
|
super( (Graphics2D) delegate );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create() {
|
||||||
|
return new RoundedSelectionGraphics( super.create() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create( int x, int y, int width, int height ) {
|
||||||
|
return new RoundedSelectionGraphics( super.create( x, y, width, height ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillRect( int x, int y, int width, int height ) {
|
||||||
|
if( !inPaintSelection &&
|
||||||
|
x == 0 && y == 0 && width == rowBounds.width && height == rowBounds.height &&
|
||||||
|
this.getColor() == rendererComponent.getBackground() )
|
||||||
|
{
|
||||||
|
inPaintSelection = true;
|
||||||
|
paintCellSelection( this, row, x, y, width, height );
|
||||||
|
inPaintSelection = false;
|
||||||
|
} else
|
||||||
|
super.fillRect( x, y, width, height );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g = new RoundedSelectionGraphics( g );
|
||||||
|
}
|
||||||
|
|
||||||
|
// paint renderer
|
||||||
|
rendererPane.paintComponent( g, rendererComponent, list, cx, rowBounds.y, cw, rowBounds.height, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
||||||
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
|
if( list.getLayoutOrientation() == JList.VERTICAL ) {
|
||||||
|
// layout orientation: VERTICAL
|
||||||
|
if( useUnitedRoundedSelection( true, false ) ) {
|
||||||
|
if( row > 0 && list.isSelectedIndex( row - 1 ) )
|
||||||
|
arcTopLeft = arcTopRight = 0;
|
||||||
|
if( row < list.getModel().getSize() - 1 && list.isSelectedIndex( row + 1 ) )
|
||||||
|
arcBottomLeft = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// layout orientation: VERTICAL_WRAP or HORIZONTAL_WRAP
|
||||||
|
Rectangle r = null;
|
||||||
|
if( useUnitedRoundedSelection( true, false ) ) {
|
||||||
|
// vertical: check whether cells above or below are selected
|
||||||
|
r = getCellBounds( list, row, row );
|
||||||
|
|
||||||
|
int topIndex = locationToIndex( list, new Point( r.x, r.y - 1 ) );
|
||||||
|
int bottomIndex = locationToIndex( list, new Point( r.x, r.y + r.height ) );
|
||||||
|
|
||||||
|
if( topIndex >= 0 && topIndex != row && list.isSelectedIndex( topIndex ) )
|
||||||
|
arcTopLeft = arcTopRight = 0;
|
||||||
|
if( bottomIndex >= 0 && bottomIndex != row && list.isSelectedIndex( bottomIndex ) )
|
||||||
|
arcBottomLeft = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( useUnitedRoundedSelection( false, true ) ) {
|
||||||
|
// horizontal: check whether cells left or right are selected
|
||||||
|
if( r == null )
|
||||||
|
r = getCellBounds( list, row, row );
|
||||||
|
|
||||||
|
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
||||||
|
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
||||||
|
|
||||||
|
// special handling for the case that last column contains less cells than the other columns
|
||||||
|
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
||||||
|
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
||||||
|
leftIndex = -1;
|
||||||
|
if( ltr && rightIndex >= 0 && rightIndex != row && rightIndex == locationToIndex( list, new Point( r.x + r.width, r.y - 1 ) ) )
|
||||||
|
rightIndex = -1;
|
||||||
|
|
||||||
|
if( leftIndex >= 0 && leftIndex != row && list.isSelectedIndex( leftIndex ) )
|
||||||
|
arcTopLeft = arcBottomLeft = 0;
|
||||||
|
if( rightIndex >= 0 && rightIndex != row && list.isSelectedIndex( rightIndex ) )
|
||||||
|
arcTopRight = arcBottomRight = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||||
|
UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useUnitedRoundedSelection( boolean vertical, boolean horizontal ) {
|
||||||
|
return selectionArc > 0 &&
|
||||||
|
(selectionInsets == null ||
|
||||||
|
(vertical && selectionInsets.top == 0 && selectionInsets.bottom == 0) ||
|
||||||
|
(horizontal && selectionInsets.left == 0 && selectionInsets.right == 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.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void paintCellSelection( JList<?> list, Graphics g, int row, int x, int y, int width, int height ) {
|
||||||
|
if( !(list.getUI() instanceof FlatListUI) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
FlatListUI ui = (FlatListUI) list.getUI();
|
||||||
|
ui.paintCellSelection( g, row, x, y, width, height );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ public class FlatMenuBarUI
|
|||||||
/** @since 2 */ @Styleable protected Insets itemMargins;
|
/** @since 2 */ @Styleable protected Insets itemMargins;
|
||||||
|
|
||||||
// used in FlatMenuUI
|
// used in FlatMenuUI
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionEmbeddedInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc = -1;
|
||||||
/** @since 2 */ @Styleable protected Color hoverBackground;
|
/** @since 2 */ @Styleable protected Color hoverBackground;
|
||||||
/** @since 2.5 */ @Styleable protected Color selectionBackground;
|
/** @since 2.5 */ @Styleable protected Color selectionBackground;
|
||||||
/** @since 2.5 */ @Styleable protected Color selectionForeground;
|
/** @since 2.5 */ @Styleable protected Color selectionForeground;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault MenuItem.acceleratorArrowGap int
|
* @uiDefault MenuItem.acceleratorArrowGap int
|
||||||
* @uiDefault MenuItem.checkBackground Color
|
* @uiDefault MenuItem.checkBackground Color
|
||||||
* @uiDefault MenuItem.checkMargins Insets
|
* @uiDefault MenuItem.checkMargins Insets
|
||||||
|
* @uiDefault MenuItem.selectionInsets Insets
|
||||||
|
* @uiDefault MenuItem.selectionArc int
|
||||||
* @uiDefault MenuItem.selectionType String null (default) or underline
|
* @uiDefault MenuItem.selectionType String null (default) or underline
|
||||||
* @uiDefault MenuItem.underlineSelectionBackground Color
|
* @uiDefault MenuItem.underlineSelectionBackground Color
|
||||||
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
||||||
@@ -91,6 +93,9 @@ public class FlatMenuItemRenderer
|
|||||||
@Styleable protected Color checkBackground = UIManager.getColor( "MenuItem.checkBackground" );
|
@Styleable protected Color checkBackground = UIManager.getColor( "MenuItem.checkBackground" );
|
||||||
@Styleable protected Insets checkMargins = UIManager.getInsets( "MenuItem.checkMargins" );
|
@Styleable protected Insets checkMargins = UIManager.getInsets( "MenuItem.checkMargins" );
|
||||||
|
|
||||||
|
/** @since 3 */ @Styleable protected Insets selectionInsets = UIManager.getInsets( "MenuItem.selectionInsets" );
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc = UIManager.getInt( "MenuItem.selectionArc" );
|
||||||
|
|
||||||
@Styleable protected Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
|
@Styleable protected Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
|
||||||
@Styleable protected Color underlineSelectionCheckBackground = UIManager.getColor( "MenuItem.underlineSelectionCheckBackground" );
|
@Styleable protected Color underlineSelectionCheckBackground = UIManager.getColor( "MenuItem.underlineSelectionCheckBackground" );
|
||||||
@Styleable protected Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
|
@Styleable protected Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
|
||||||
@@ -337,10 +342,16 @@ public class FlatMenuItemRenderer
|
|||||||
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
|
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
|
||||||
debug*/
|
debug*/
|
||||||
|
|
||||||
|
boolean armedOrSelected = isArmedOrSelected( menuItem );
|
||||||
boolean underlineSelection = isUnderlineSelection();
|
boolean underlineSelection = isUnderlineSelection();
|
||||||
paintBackground( g, underlineSelection ? underlineSelectionBackground : selectionBackground );
|
|
||||||
if( underlineSelection && isArmedOrSelected( menuItem ) )
|
paintBackground( g );
|
||||||
paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
|
if( armedOrSelected ) {
|
||||||
|
if( underlineSelection )
|
||||||
|
paintUnderlineSelection( g, underlineSelectionBackground, underlineSelectionColor, underlineSelectionHeight );
|
||||||
|
else
|
||||||
|
paintSelection( g, selectionBackground, selectionInsets, selectionArc );
|
||||||
|
}
|
||||||
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 );
|
||||||
@@ -348,21 +359,35 @@ debug*/
|
|||||||
paintArrowIcon( g, arrowRect, arrowIcon );
|
paintArrowIcon( g, arrowRect, arrowIcon );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
/** @since 3 */
|
||||||
boolean armedOrSelected = isArmedOrSelected( menuItem );
|
protected void paintBackground( Graphics g ) {
|
||||||
if( menuItem.isOpaque() || armedOrSelected ) {
|
if( menuItem.isOpaque() ) {
|
||||||
// paint background
|
g.setColor( menuItem.getBackground() );
|
||||||
g.setColor( armedOrSelected
|
|
||||||
? deriveBackground( selectionBackground )
|
|
||||||
: menuItem.getBackground() );
|
|
||||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
|
/** @since 3 */
|
||||||
|
protected void paintSelection( Graphics g, Color selectionBackground, Insets selectionInsets, int selectionArc ) {
|
||||||
|
float arc = scale( selectionArc / 2f );
|
||||||
|
|
||||||
|
g.setColor( deriveBackground( selectionBackground ) );
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, 0, 0, menuItem.getWidth(), menuItem.getHeight(),
|
||||||
|
scale( selectionInsets ), arc, arc, arc, arc, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionBackground,
|
||||||
|
Color underlineSelectionColor, int underlineSelectionHeight )
|
||||||
|
{
|
||||||
int width = menuItem.getWidth();
|
int width = menuItem.getWidth();
|
||||||
int height = menuItem.getHeight();
|
int height = menuItem.getHeight();
|
||||||
|
|
||||||
|
// paint background
|
||||||
|
g.setColor( deriveBackground( underlineSelectionBackground ) );
|
||||||
|
g.fillRect( 0, 0, width, height );
|
||||||
|
|
||||||
|
// paint underline
|
||||||
int underlineHeight = scale( underlineSelectionHeight );
|
int underlineHeight = scale( underlineSelectionHeight );
|
||||||
g.setColor( underlineSelectionColor );
|
g.setColor( underlineSelectionColor );
|
||||||
if( isTopLevelMenu( menuItem ) ) {
|
if( isTopLevelMenu( menuItem ) ) {
|
||||||
@@ -431,10 +456,11 @@ debug*/
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// center because the real icon may be smaller than dimension in iconRect
|
// center because the real icon may be smaller than dimension in iconRect
|
||||||
|
int x = iconRect.x + centerOffset( iconRect.width, icon.getIconWidth() );
|
||||||
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
||||||
|
|
||||||
// paint
|
// paint
|
||||||
icon.paintIcon( menuItem, g, iconRect.x, y );
|
icon.paintIcon( menuItem, g, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void paintText( Graphics g, JMenuItem menuItem,
|
protected static void paintText( Graphics g, JMenuItem menuItem,
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Window;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@@ -32,7 +34,9 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.MouseInputListener;
|
import javax.swing.event.MouseInputListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
@@ -75,9 +79,12 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
*
|
*
|
||||||
* <!-- FlatMenuRenderer -->
|
* <!-- FlatMenuRenderer -->
|
||||||
*
|
*
|
||||||
|
* @uiDefault MenuBar.selectionInsets Insets
|
||||||
|
* @uiDefault MenuBar.selectionEmbeddedInsets Insets
|
||||||
|
* @uiDefault MenuBar.selectionArc int
|
||||||
* @uiDefault MenuBar.hoverBackground Color
|
* @uiDefault MenuBar.hoverBackground Color
|
||||||
* @uiDefault MenuBar.selectionBackground Color
|
* @uiDefault MenuBar.selectionBackground Color optional; defaults to Menu.selectionBackground
|
||||||
* @uiDefault MenuBar.selectionForeground Color
|
* @uiDefault MenuBar.selectionForeground Color optional; defaults to Menu.selectionForeground
|
||||||
* @uiDefault MenuBar.underlineSelectionBackground Color
|
* @uiDefault MenuBar.underlineSelectionBackground Color
|
||||||
* @uiDefault MenuBar.underlineSelectionColor Color
|
* @uiDefault MenuBar.underlineSelectionColor Color
|
||||||
* @uiDefault MenuBar.underlineSelectionHeight int
|
* @uiDefault MenuBar.underlineSelectionHeight int
|
||||||
@@ -225,12 +232,15 @@ public class FlatMenuUI
|
|||||||
protected class FlatMenuRenderer
|
protected class FlatMenuRenderer
|
||||||
extends FlatMenuItemRenderer
|
extends FlatMenuItemRenderer
|
||||||
{
|
{
|
||||||
|
/** @since 3 */ protected Insets menuBarSelectionInsets = UIManager.getInsets( "MenuBar.selectionInsets" );
|
||||||
|
/** @since 3 */ protected Insets menuBarSelectionEmbeddedInsets = UIManager.getInsets( "MenuBar.selectionEmbeddedInsets" );
|
||||||
|
/** @since 3 */ protected int menuBarSelectionArc = UIManager.getInt( "MenuBar.selectionArc" );
|
||||||
protected Color hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
protected Color hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
||||||
protected Color menuBarSelectionBackground = UIManager.getColor( "MenuBar.selectionBackground" );
|
/** @since 2.5 */ protected Color menuBarSelectionBackground = UIManager.getColor( "MenuBar.selectionBackground" );
|
||||||
protected Color menuBarSelectionForeground = UIManager.getColor( "MenuBar.selectionForeground" );
|
/** @since 2.5 */ protected Color menuBarSelectionForeground = UIManager.getColor( "MenuBar.selectionForeground" );
|
||||||
protected Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground );
|
protected Color menuBarUnderlineSelectionBackground = UIManager.getColor( "MenuBar.underlineSelectionBackground" );
|
||||||
protected Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor );
|
protected Color menuBarUnderlineSelectionColor = UIManager.getColor( "MenuBar.underlineSelectionColor" );
|
||||||
protected int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight );
|
protected int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", -1 );
|
||||||
|
|
||||||
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
||||||
Font acceleratorFont, String acceleratorDelimiter )
|
Font acceleratorFont, String acceleratorDelimiter )
|
||||||
@@ -238,46 +248,76 @@ public class FlatMenuUI
|
|||||||
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
super.paintBackground( g );
|
||||||
if( isUnderlineSelection() )
|
|
||||||
selectionBackground = getStyleFromMenuBarUI( ui -> ui.underlineSelectionBackground, menuBarUnderlineSelectionBackground );
|
|
||||||
else {
|
|
||||||
selectionBackground = getStyleFromMenuBarUI( ui -> ui.selectionBackground,
|
|
||||||
menuBarSelectionBackground != null ? menuBarSelectionBackground : selectionBackground );
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonModel model = menuItem.getModel();
|
if( ((JMenu)menuItem).isTopLevelMenu() && isHover() ) {
|
||||||
if( model.isRollover() && !model.isArmed() && !model.isSelected() && model.isEnabled() ) {
|
// paint hover background
|
||||||
g.setColor( deriveBackground( getStyleFromMenuBarUI( ui -> ui.hoverBackground, hoverBackground ) ) );
|
Color color = deriveBackground( getStyleFromMenuBarUI( ui -> ui.hoverBackground, hoverBackground ) );
|
||||||
|
if( isUnderlineSelection() ) {
|
||||||
|
g.setColor( color );
|
||||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||||
return;
|
} else
|
||||||
|
paintSelection( g, color, selectionInsets, selectionArc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.paintBackground( g, selectionBackground );
|
/** @since 3 */
|
||||||
|
@Override
|
||||||
|
protected void paintSelection( Graphics g, Color selectionBackground, Insets selectionInsets, int selectionArc ) {
|
||||||
|
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||||
|
if( !isHover() )
|
||||||
|
selectionBackground = getStyleFromMenuBarUI( ui -> ui.selectionBackground, menuBarSelectionBackground, selectionBackground );
|
||||||
|
|
||||||
|
JMenuBar menuBar = (JMenuBar) menuItem.getParent();
|
||||||
|
JRootPane rootPane = SwingUtilities.getRootPane( menuBar );
|
||||||
|
if( rootPane != null && rootPane.getParent() instanceof Window &&
|
||||||
|
rootPane.getJMenuBar() == menuBar &&
|
||||||
|
FlatRootPaneUI.isMenuBarEmbedded( rootPane ) )
|
||||||
|
{
|
||||||
|
selectionInsets = getStyleFromMenuBarUI( ui -> ui.selectionEmbeddedInsets, menuBarSelectionEmbeddedInsets );
|
||||||
|
} else
|
||||||
|
selectionInsets = getStyleFromMenuBarUI( ui -> ui.selectionInsets, menuBarSelectionInsets );
|
||||||
|
|
||||||
|
selectionArc = getStyleFromMenuBarUI( ui -> (ui.selectionArc != -1)
|
||||||
|
? ui.selectionArc : null, menuBarSelectionArc );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintSelection( g, selectionBackground, selectionInsets, selectionArc );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
@Override
|
||||||
|
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionBackground,
|
||||||
|
Color underlineSelectionColor, int underlineSelectionHeight )
|
||||||
|
{
|
||||||
|
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||||
|
underlineSelectionBackground = getStyleFromMenuBarUI( ui -> ui.underlineSelectionBackground, menuBarUnderlineSelectionBackground, underlineSelectionBackground );
|
||||||
|
underlineSelectionColor = getStyleFromMenuBarUI( ui -> ui.underlineSelectionColor, menuBarUnderlineSelectionColor, underlineSelectionColor );
|
||||||
|
underlineSelectionHeight = getStyleFromMenuBarUI( ui -> (ui.underlineSelectionHeight != -1) ? ui.underlineSelectionHeight : null,
|
||||||
|
(menuBarUnderlineSelectionHeight != -1) ? menuBarUnderlineSelectionHeight : underlineSelectionHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintUnderlineSelection( g, underlineSelectionBackground, underlineSelectionColor, underlineSelectionHeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintText( Graphics g, Rectangle textRect, String text, Color selectionForeground, Color disabledForeground ) {
|
protected void paintText( Graphics g, Rectangle textRect, String text, Color selectionForeground, Color disabledForeground ) {
|
||||||
if( ((JMenu)menuItem).isTopLevelMenu() && !isUnderlineSelection() ) {
|
if( ((JMenu)menuItem).isTopLevelMenu() && !isUnderlineSelection() )
|
||||||
selectionForeground = getStyleFromMenuBarUI( ui -> ui.selectionForeground,
|
selectionForeground = getStyleFromMenuBarUI( ui -> ui.selectionForeground, menuBarSelectionForeground, selectionForeground );
|
||||||
menuBarSelectionForeground != null ? menuBarSelectionForeground : selectionForeground );
|
|
||||||
}
|
|
||||||
|
|
||||||
super.paintText( g, textRect, text, selectionForeground, disabledForeground );
|
super.paintText( g, textRect, text, selectionForeground, disabledForeground );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean isHover() {
|
||||||
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
|
ButtonModel model = menuItem.getModel();
|
||||||
if( ((JMenu)menuItem).isTopLevelMenu() ) {
|
return model.isRollover() && !model.isArmed() && !model.isSelected() && model.isEnabled();
|
||||||
underlineSelectionColor = getStyleFromMenuBarUI( ui -> ui.underlineSelectionColor, menuBarUnderlineSelectionColor );
|
|
||||||
underlineSelectionHeight = getStyleFromMenuBarUI( ui -> (ui.underlineSelectionHeight != -1)
|
|
||||||
? ui.underlineSelectionHeight : null, menuBarUnderlineSelectionHeight );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
|
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue, T defaultValue2 ) {
|
||||||
|
return getStyleFromMenuBarUI( f, (defaultValue != null) ? defaultValue : defaultValue2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue ) {
|
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue ) {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.CodeSource;
|
||||||
import com.formdev.flatlaf.FlatSystemProperties;
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.NativeLibrary;
|
import com.formdev.flatlaf.util.NativeLibrary;
|
||||||
@@ -46,13 +48,13 @@ class FlatNativeLibrary
|
|||||||
if( nativeLibrary != null )
|
if( nativeLibrary != null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String libraryName;
|
String classifier;
|
||||||
|
String ext;
|
||||||
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
|
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
|
||||||
// Windows: requires Windows 10/11 (x86 or x86_64)
|
// Windows: requires Windows 10/11 (x86 or x86_64)
|
||||||
|
|
||||||
libraryName = "flatlaf-windows-x86";
|
classifier = SystemInfo.isX86_64 ? "windows-x86_64" : "windows-x86";
|
||||||
if( SystemInfo.isX86_64 )
|
ext = "dll";
|
||||||
libraryName += "_64";
|
|
||||||
|
|
||||||
// In Java 8, load jawt.dll (part of JRE) explicitly because it
|
// In Java 8, load jawt.dll (part of JRE) explicitly because it
|
||||||
// is not found when running application with <jdk>/bin/java.exe.
|
// is not found when running application with <jdk>/bin/java.exe.
|
||||||
@@ -64,7 +66,8 @@ class FlatNativeLibrary
|
|||||||
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
||||||
// Linux: requires x86_64
|
// Linux: requires x86_64
|
||||||
|
|
||||||
libraryName = "flatlaf-linux-x86_64";
|
classifier = "linux-x86_64";
|
||||||
|
ext = "so";
|
||||||
|
|
||||||
// Load libjawt.so (part of JRE) explicitly because it is not found
|
// Load libjawt.so (part of JRE) explicitly because it is not found
|
||||||
// in all Java versions/distributions.
|
// in all Java versions/distributions.
|
||||||
@@ -76,10 +79,13 @@ 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 = createNativeLibrary( libraryName );
|
nativeLibrary = createNativeLibrary( classifier, ext );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NativeLibrary createNativeLibrary( String libraryName ) {
|
private static NativeLibrary createNativeLibrary( String classifier, String ext ) {
|
||||||
|
String libraryName = "flatlaf-" + classifier;
|
||||||
|
|
||||||
|
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
|
||||||
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
|
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
|
||||||
if( libraryPath != null ) {
|
if( libraryPath != null ) {
|
||||||
if( "system".equals( libraryPath ) ) {
|
if( "system".equals( libraryPath ) ) {
|
||||||
@@ -97,9 +103,74 @@ class FlatNativeLibrary
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load from beside the FlatLaf jar
|
||||||
|
// e.g. for flatlaf-3.1.jar, load flatlaf-3.1-windows-x86_64.dll (from same directory)
|
||||||
|
File libraryFile = findLibraryBesideJar( classifier, ext );
|
||||||
|
if( libraryFile != null )
|
||||||
|
return new NativeLibrary( libraryFile, true );
|
||||||
|
|
||||||
|
// 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, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for a native library beside the jar that contains this class
|
||||||
|
* (usually the FlatLaf jar).
|
||||||
|
* The native library must be in the same directory (or in "../bin" if jar is in "lib")
|
||||||
|
* as the jar and have the same basename as the jar.
|
||||||
|
* If FlatLaf jar is repackaged into fat/uber application jar, "-flatlaf" is appended to jar basename.
|
||||||
|
* The classifier and the extension are appended to the jar basename.
|
||||||
|
*
|
||||||
|
* E.g.
|
||||||
|
* flatlaf-3.1.jar
|
||||||
|
* flatlaf-3.1-windows-x86_64.dll
|
||||||
|
* flatlaf-3.1-linux-x86_64.so
|
||||||
|
*/
|
||||||
|
private static File findLibraryBesideJar( String classifier, String ext ) {
|
||||||
|
try {
|
||||||
|
// get location of FlatLaf jar
|
||||||
|
CodeSource codeSource = FlatNativeLibrary.class.getProtectionDomain().getCodeSource();
|
||||||
|
URL jarUrl = (codeSource != null) ? codeSource.getLocation() : null;
|
||||||
|
if( jarUrl == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// if url is not a file, then we're running in a special environment (e.g. WebStart)
|
||||||
|
if( !"file".equals( jarUrl.getProtocol() ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
File jarFile = new File( jarUrl.toURI() );
|
||||||
|
|
||||||
|
// if jarFile is a directory, then we're in a development environment
|
||||||
|
if( !jarFile.isFile() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// build library file
|
||||||
|
String jarName = jarFile.getName();
|
||||||
|
String jarBasename = jarName.substring( 0, jarName.lastIndexOf( '.' ) );
|
||||||
|
File parent = jarFile.getParentFile();
|
||||||
|
String libraryName = jarBasename
|
||||||
|
+ (jarBasename.contains( "flatlaf" ) ? "" : "-flatlaf")
|
||||||
|
+ '-' + classifier + '.' + ext;
|
||||||
|
|
||||||
|
// check whether native library exists in same directory as jar
|
||||||
|
File libraryFile = new File( parent, libraryName );
|
||||||
|
if( libraryFile.isFile() )
|
||||||
|
return libraryFile;
|
||||||
|
|
||||||
|
// if jar is in "lib" directory, then also check whether library exists
|
||||||
|
// in "../bin" directory
|
||||||
|
if( parent.getName().equalsIgnoreCase( "lib" ) ) {
|
||||||
|
libraryFile = new File( parent.getParentFile(), "bin/" + libraryName );
|
||||||
|
if( libraryFile.isFile() )
|
||||||
|
return libraryFile;
|
||||||
|
}
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static void loadJAWT() {
|
private static void loadJAWT() {
|
||||||
try {
|
try {
|
||||||
System.loadLibrary( "jawt" );
|
System.loadLibrary( "jawt" );
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Native methods for Linux.
|
* Native methods for Linux.
|
||||||
@@ -35,7 +36,7 @@ import javax.swing.JFrame;
|
|||||||
class FlatNativeLinuxLibrary
|
class FlatNativeLinuxLibrary
|
||||||
{
|
{
|
||||||
static boolean isLoaded() {
|
static boolean isLoaded() {
|
||||||
return FlatNativeLibrary.isLoaded();
|
return SystemInfo.isLinux && FlatNativeLibrary.isLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
// direction for _NET_WM_MOVERESIZE message
|
// direction for _NET_WM_MOVERESIZE message
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.Window;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native methods for Windows.
|
||||||
|
* <p>
|
||||||
|
* <b>Note</b>: This is private API. Do not use!
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public class FlatNativeWindowsLibrary
|
||||||
|
{
|
||||||
|
private static long osBuildNumber = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
public static boolean isLoaded() {
|
||||||
|
return SystemInfo.isWindows && FlatNativeLibrary.isLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Windows operating system build number.
|
||||||
|
* <p>
|
||||||
|
* Invokes Win32 API method {@code GetVersionEx()} and returns {@code OSVERSIONINFO.dwBuildNumber}.
|
||||||
|
* See https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa
|
||||||
|
*/
|
||||||
|
public static long getOSBuildNumber() {
|
||||||
|
if( osBuildNumber == Long.MIN_VALUE )
|
||||||
|
osBuildNumber = getOSBuildNumberImpl();
|
||||||
|
return osBuildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes Win32 API method {@code GetVersionEx()} and returns {@code OSVERSIONINFO.dwBuildNumber}.
|
||||||
|
* See https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa
|
||||||
|
*/
|
||||||
|
private native static long getOSBuildNumberImpl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Windows window handle (HWND) for the given Swing window.
|
||||||
|
* <p>
|
||||||
|
* Note that the underlying Windows window must be already created,
|
||||||
|
* otherwise this method returns zero. Use following to ensure this:
|
||||||
|
* <pre>{@code
|
||||||
|
* if( !window.isDisplayable() )
|
||||||
|
* window.addNotify();
|
||||||
|
* }</pre>
|
||||||
|
* or invoke this method after packing the window. E.g.
|
||||||
|
* <pre>{@code
|
||||||
|
* window.pack();
|
||||||
|
* long hwnd = getHWND( window );
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
|
public native static long getHWND( Window window );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DWM_WINDOW_CORNER_PREFERENCE
|
||||||
|
* see https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_window_corner_preference
|
||||||
|
*/
|
||||||
|
public static final int
|
||||||
|
DWMWCP_DEFAULT = 0,
|
||||||
|
DWMWCP_DONOTROUND = 1,
|
||||||
|
DWMWCP_ROUND = 2,
|
||||||
|
DWMWCP_ROUNDSMALL = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rounded corner preference for the window.
|
||||||
|
* Allowed values are {@link #DWMWCP_DEFAULT}, {@link #DWMWCP_DONOTROUND},
|
||||||
|
* {@link #DWMWCP_ROUND} and {@link #DWMWCP_ROUNDSMALL}.
|
||||||
|
* <p>
|
||||||
|
* Invokes Win32 API method {@code DwmSetWindowAttribute(DWMWA_WINDOW_CORNER_PREFERENCE)}.
|
||||||
|
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
||||||
|
* <p>
|
||||||
|
* Supported since Windows 11 Build 22000.
|
||||||
|
*/
|
||||||
|
public native static boolean setWindowCornerPreference( long hwnd, int cornerPreference );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the color of the window border.
|
||||||
|
* The red/green/blue values must be in range {@code 0 - 255}.
|
||||||
|
* If red is {@code -1}, then the system default border color is used (useful to reset the border color).
|
||||||
|
* If red is {@code -2}, then no border is painted.
|
||||||
|
* <p>
|
||||||
|
* Invokes Win32 API method {@code DwmSetWindowAttribute(DWMWA_BORDER_COLOR)}.
|
||||||
|
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
||||||
|
* <p>
|
||||||
|
* Supported since Windows 11 Build 22000.
|
||||||
|
*/
|
||||||
|
public native static boolean setWindowBorderColor( long hwnd, int red, int green, int blue );
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ import java.lang.reflect.Method;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLayeredPane;
|
import javax.swing.JLayeredPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JToolTip;
|
import javax.swing.JToolTip;
|
||||||
import javax.swing.JWindow;
|
import javax.swing.JWindow;
|
||||||
import javax.swing.Popup;
|
import javax.swing.Popup;
|
||||||
@@ -52,6 +53,9 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.ToolTipManager;
|
import javax.swing.ToolTipManager;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.border.LineBorder;
|
||||||
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -88,6 +92,17 @@ public class FlatPopupFactory
|
|||||||
if( SystemInfo.isMacOS || SystemInfo.isLinux )
|
if( SystemInfo.isMacOS || SystemInfo.isLinux )
|
||||||
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
||||||
|
|
||||||
|
// Windows 11 with FlatLaf native library can use rounded corners and shows drop shadow for heavy weight popups
|
||||||
|
int borderCornerRadius;
|
||||||
|
if( isWindows11BorderSupported() &&
|
||||||
|
(borderCornerRadius = getBorderCornerRadius( owner, contents )) > 0 )
|
||||||
|
{
|
||||||
|
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
||||||
|
if( popup.popupWindow != null )
|
||||||
|
setupWindows11Border( popup.popupWindow, contents, borderCornerRadius );
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
// create drop shadow popup
|
// create drop shadow popup
|
||||||
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
||||||
}
|
}
|
||||||
@@ -166,19 +181,39 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOptionEnabled( Component owner, Component contents, String clientKey, String uiKey ) {
|
private boolean isOptionEnabled( Component owner, Component contents, String clientKey, String uiKey ) {
|
||||||
if( owner instanceof JComponent ) {
|
Object value = getOption( owner, contents, clientKey, uiKey );
|
||||||
Boolean b = FlatClientProperties.clientPropertyBooleanStrict( (JComponent) owner, clientKey, null );
|
return (value instanceof Boolean) ? (Boolean) value : false;
|
||||||
if( b != null )
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( contents instanceof JComponent ) {
|
private int getBorderCornerRadius( Component owner, Component contents ) {
|
||||||
Boolean b = FlatClientProperties.clientPropertyBooleanStrict( (JComponent) contents, clientKey, null );
|
String uiKey =
|
||||||
if( b != null )
|
(contents instanceof BasicComboPopup) ? "ComboBox.borderCornerRadius" :
|
||||||
return b;
|
(contents instanceof JPopupMenu) ? "PopupMenu.borderCornerRadius" :
|
||||||
|
(contents instanceof JToolTip) ? "ToolTip.borderCornerRadius" :
|
||||||
|
"Popup.borderCornerRadius";
|
||||||
|
|
||||||
|
Object value = getOption( owner, contents, FlatClientProperties.POPUP_BORDER_CORNER_RADIUS, uiKey );
|
||||||
|
return (value instanceof Integer) ? (Integer) value : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UIManager.getBoolean( uiKey );
|
/**
|
||||||
|
* Get option from:
|
||||||
|
* <ol>
|
||||||
|
* <li>client property {@code clientKey} of {@code owner}
|
||||||
|
* <li>client property {@code clientKey} of {@code contents}
|
||||||
|
* <li>UI property {@code uiKey}
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
private Object getOption( Component owner, Component contents, String clientKey, String uiKey ) {
|
||||||
|
for( Component c : new Component[] { owner, contents } ) {
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Object value = ((JComponent)c).getClientProperty( clientKey );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UIManager.get( uiKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -300,6 +335,60 @@ public class FlatPopupFactory
|
|||||||
((JComponent)owner).getToolTipLocation( me ) != null;
|
((JComponent)owner).getToolTipLocation( me ) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isWindows11BorderSupported() {
|
||||||
|
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setupWindows11Border( Window popupWindow, Component contents, int borderCornerRadius ) {
|
||||||
|
// make sure that the Windows 11 window is created
|
||||||
|
if( !popupWindow.isDisplayable() )
|
||||||
|
popupWindow.addNotify();
|
||||||
|
|
||||||
|
// get window handle
|
||||||
|
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
||||||
|
|
||||||
|
// set corner preference
|
||||||
|
int cornerPreference = (borderCornerRadius <= 4)
|
||||||
|
? FlatNativeWindowsLibrary.DWMWCP_ROUNDSMALL // 4px
|
||||||
|
: FlatNativeWindowsLibrary.DWMWCP_ROUND; // 8px
|
||||||
|
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, cornerPreference );
|
||||||
|
|
||||||
|
// set border color
|
||||||
|
int red = -1; // use system default color
|
||||||
|
int green = 0;
|
||||||
|
int blue = 0;
|
||||||
|
if( contents instanceof JComponent ) {
|
||||||
|
Border border = ((JComponent)contents).getBorder();
|
||||||
|
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
|
||||||
|
|
||||||
|
// get color from border of contents (e.g. JPopupMenu or JToolTip)
|
||||||
|
Color borderColor = null;
|
||||||
|
if( border instanceof FlatLineBorder )
|
||||||
|
borderColor = ((FlatLineBorder)border).getLineColor();
|
||||||
|
else if( border instanceof LineBorder )
|
||||||
|
borderColor = ((LineBorder)border).getLineColor();
|
||||||
|
else if( border instanceof EmptyBorder )
|
||||||
|
red = -2; // do not paint border
|
||||||
|
|
||||||
|
if( borderColor != null ) {
|
||||||
|
red = borderColor.getRed();
|
||||||
|
green = borderColor.getGreen();
|
||||||
|
blue = borderColor.getBlue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FlatNativeWindowsLibrary.setWindowBorderColor( hwnd, red, green, blue );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void resetWindows11Border( Window popupWindow ) {
|
||||||
|
// get window handle
|
||||||
|
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
||||||
|
if( hwnd == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// reset corner preference
|
||||||
|
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, FlatNativeWindowsLibrary.DWMWCP_DONOTROUND );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class NonFlashingPopup ---------------------------------------------
|
//---- class NonFlashingPopup ---------------------------------------------
|
||||||
|
|
||||||
private class NonFlashingPopup
|
private class NonFlashingPopup
|
||||||
@@ -431,6 +520,14 @@ public class FlatPopupFactory
|
|||||||
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
|
||||||
|
if( isWindows11BorderSupported() ) {
|
||||||
|
resetWindows11Border( popupWindow );
|
||||||
|
if( dropShadowWindow != null )
|
||||||
|
resetWindows11Border( dropShadowWindow );
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mediumWeightPanel = (Panel) SwingUtilities.getAncestorOfClass( Panel.class, contents );
|
mediumWeightPanel = (Panel) SwingUtilities.getAncestorOfClass( Panel.class, contents );
|
||||||
if( mediumWeightPanel != null ) {
|
if( mediumWeightPanel != null ) {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import javax.swing.plaf.basic.BasicComboPopup;
|
|||||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
||||||
import javax.swing.plaf.basic.DefaultMenuLayout;
|
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||||
|
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.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
@@ -297,6 +298,9 @@ public class FlatPopupMenuUI
|
|||||||
popup.addMenuKeyListener( this );
|
popup.addMenuKeyListener( this );
|
||||||
|
|
||||||
updateArrowButtons();
|
updateArrowButtons();
|
||||||
|
|
||||||
|
putClientProperty( FlatClientProperties.POPUP_BORDER_CORNER_RADIUS,
|
||||||
|
UIManager.getInt( "PopupMenu.borderCornerRadius" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void scroll( int unitsToScroll ) {
|
void scroll( int unitsToScroll ) {
|
||||||
|
|||||||
@@ -349,11 +349,23 @@ public class FlatRootPaneUI
|
|||||||
titlePane.updateIcon();
|
titlePane.updateIcon();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.TITLE_BAR_SHOW_TITLE:
|
||||||
|
case FlatClientProperties.TITLE_BAR_SHOW_ICONIFFY:
|
||||||
|
case FlatClientProperties.TITLE_BAR_SHOW_MAXIMIZE:
|
||||||
|
case FlatClientProperties.TITLE_BAR_SHOW_CLOSE:
|
||||||
|
if( titlePane != null )
|
||||||
|
titlePane.updateVisibility();
|
||||||
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.TITLE_BAR_BACKGROUND:
|
case FlatClientProperties.TITLE_BAR_BACKGROUND:
|
||||||
case FlatClientProperties.TITLE_BAR_FOREGROUND:
|
case FlatClientProperties.TITLE_BAR_FOREGROUND:
|
||||||
if( titlePane != null )
|
if( titlePane != null )
|
||||||
titlePane.titleBarColorsChanged();
|
titlePane.titleBarColorsChanged();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.GLASS_PANE_FULL_HEIGHT:
|
||||||
|
rootPane.revalidate();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,11 +446,11 @@ public class FlatRootPaneUI
|
|||||||
int width = rootPane.getWidth() - insets.left - insets.right;
|
int width = rootPane.getWidth() - insets.left - insets.right;
|
||||||
int height = rootPane.getHeight() - insets.top - insets.bottom;
|
int height = rootPane.getHeight() - insets.top - insets.bottom;
|
||||||
|
|
||||||
|
// layered pane
|
||||||
if( rootPane.getLayeredPane() != null )
|
if( rootPane.getLayeredPane() != null )
|
||||||
rootPane.getLayeredPane().setBounds( x, y, width, height );
|
rootPane.getLayeredPane().setBounds( x, y, width, height );
|
||||||
if( rootPane.getGlassPane() != null )
|
|
||||||
rootPane.getGlassPane().setBounds( x, y, width, height );
|
|
||||||
|
|
||||||
|
// title pane
|
||||||
int nextY = 0;
|
int nextY = 0;
|
||||||
if( titlePane != null ) {
|
if( titlePane != null ) {
|
||||||
int prefHeight = !isFullScreen ? titlePane.getPreferredSize().height : 0;
|
int prefHeight = !isFullScreen ? titlePane.getPreferredSize().height : 0;
|
||||||
@@ -446,6 +458,15 @@ public class FlatRootPaneUI
|
|||||||
nextY += prefHeight;
|
nextY += prefHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// glass pane
|
||||||
|
if( rootPane.getGlassPane() != null ) {
|
||||||
|
boolean fullHeight = FlatClientProperties.clientPropertyBoolean(
|
||||||
|
rootPane, FlatClientProperties.GLASS_PANE_FULL_HEIGHT, false );
|
||||||
|
int offset = fullHeight ? 0 : nextY;
|
||||||
|
rootPane.getGlassPane().setBounds( x, y + offset, width, height - offset );
|
||||||
|
}
|
||||||
|
|
||||||
|
// menu bar
|
||||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||||
if( menuBar != null && menuBar.isVisible() ) {
|
if( menuBar != null && menuBar.isVisible() ) {
|
||||||
boolean embedded = !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded();
|
boolean embedded = !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded();
|
||||||
@@ -459,10 +480,12 @@ public class FlatRootPaneUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// content pane
|
||||||
Container contentPane = rootPane.getContentPane();
|
Container contentPane = rootPane.getContentPane();
|
||||||
if( contentPane != null )
|
if( contentPane != null )
|
||||||
contentPane.setBounds( 0, nextY, width, Math.max( height - nextY, 0 ) );
|
contentPane.setBounds( 0, nextY, width, Math.max( height - nextY, 0 ) );
|
||||||
|
|
||||||
|
// title pane
|
||||||
if( titlePane != null )
|
if( titlePane != null )
|
||||||
titlePane.menuBarLayouted();
|
titlePane.menuBarLayouted();
|
||||||
}
|
}
|
||||||
@@ -528,7 +551,7 @@ public class FlatRootPaneUI
|
|||||||
|
|
||||||
protected boolean isWindowMaximized( Component c ) {
|
protected boolean isWindowMaximized( Component c ) {
|
||||||
Container parent = c.getParent();
|
Container parent = c.getParent();
|
||||||
return parent instanceof Frame && (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
return parent instanceof Frame && (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.SpinnerUI;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +38,19 @@ public class FlatRoundBorder
|
|||||||
// 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)
|
||||||
/** @since 2 */ @Styleable protected Boolean roundRect;
|
/** @since 2 */ @Styleable protected Boolean roundRect;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
// make mac style spinner border smaller (border does not surround arrow buttons)
|
||||||
|
if( isMacStyleSpinner( c ) ) {
|
||||||
|
int macStyleButtonsWidth = ((FlatSpinnerUI)((JSpinner)c).getUI()).getMacStyleButtonsWidth();
|
||||||
|
width -= macStyleButtonsWidth;
|
||||||
|
if( !c.getComponentOrientation().isLeftToRight() )
|
||||||
|
x += macStyleButtonsWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintBorder( c, g, x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getArc( Component c ) {
|
protected int getArc( Component c ) {
|
||||||
if( isCellEditor( c ) )
|
if( isCellEditor( c ) )
|
||||||
@@ -43,6 +59,17 @@ public class FlatRoundBorder
|
|||||||
Boolean roundRect = FlatUIUtils.isRoundRect( c );
|
Boolean roundRect = FlatUIUtils.isRoundRect( c );
|
||||||
if( roundRect == null )
|
if( roundRect == null )
|
||||||
roundRect = this.roundRect;
|
roundRect = this.roundRect;
|
||||||
return roundRect != null ? (roundRect ? Short.MAX_VALUE : 0) : arc;
|
return roundRect != null
|
||||||
|
? (roundRect ? Short.MAX_VALUE : 0)
|
||||||
|
: (isMacStyleSpinner( c ) ? 0 : arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMacStyleSpinner( Component c ) {
|
||||||
|
if( c instanceof JSpinner ) {
|
||||||
|
SpinnerUI ui = ((JSpinner)c).getUI();
|
||||||
|
if( ui instanceof FlatSpinnerUI )
|
||||||
|
return ((FlatSpinnerUI)ui).isMacStyle();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ debug*/
|
|||||||
public static Shape createDirectionalThumbShape( float x, float y, float w, float h, float arc ) {
|
public static Shape createDirectionalThumbShape( float x, float y, float w, float h, float arc ) {
|
||||||
float wh = w / 2;
|
float wh = w / 2;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float();
|
Path2D path = new Path2D.Float( Path2D.WIND_NON_ZERO, 9 );
|
||||||
path.moveTo( x + wh, y + h );
|
path.moveTo( x + wh, y + h );
|
||||||
path.lineTo( x, y + (h - wh) );
|
path.lineTo( x, y + (h - wh) );
|
||||||
path.lineTo( x, y + arc );
|
path.lineTo( x, y + arc );
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatSpinnerUI -->
|
* <!-- FlatSpinnerUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Spinner.buttonStyle String button (default) or none
|
* @uiDefault Spinner.buttonStyle String button (default), mac or none
|
||||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
* @uiDefault Component.isIntelliJTheme boolean
|
||||||
* @uiDefault Spinner.disabledBackground Color
|
* @uiDefault Spinner.disabledBackground Color
|
||||||
@@ -340,7 +340,25 @@ public class FlatSpinnerUI
|
|||||||
|
|
||||||
private Component createArrowButton( int direction, String name ) {
|
private Component createArrowButton( int direction, String name ) {
|
||||||
FlatArrowButton button = new FlatArrowButton( direction, arrowType, buttonArrowColor,
|
FlatArrowButton button = new FlatArrowButton( direction, arrowType, buttonArrowColor,
|
||||||
buttonDisabledArrowColor, buttonHoverArrowColor, null, buttonPressedArrowColor, null );
|
buttonDisabledArrowColor, buttonHoverArrowColor, null, buttonPressedArrowColor, null )
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public int getArrowWidth() {
|
||||||
|
return isMacStyle() ? 7 : super.getArrowWidth();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return isMacStyle() ? 1.5f : super.getArrowThickness();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public float getYOffset() {
|
||||||
|
return isMacStyle() ? 0 : super.getYOffset();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return isMacStyle() ? false : super.isRoundBorderAutoXOffset();
|
||||||
|
}
|
||||||
|
};
|
||||||
button.setName( name );
|
button.setName( name );
|
||||||
button.setYOffset( (direction == SwingConstants.NORTH) ? 1.25f : -1.25f );
|
button.setYOffset( (direction == SwingConstants.NORTH) ? 1.25f : -1.25f );
|
||||||
if( direction == SwingConstants.NORTH )
|
if( direction == SwingConstants.NORTH )
|
||||||
@@ -374,10 +392,13 @@ public class FlatSpinnerUI
|
|||||||
int width = c.getWidth();
|
int width = c.getWidth();
|
||||||
int height = c.getHeight();
|
int height = c.getHeight();
|
||||||
boolean enabled = spinner.isEnabled();
|
boolean enabled = spinner.isEnabled();
|
||||||
|
boolean ltr = spinner.getComponentOrientation().isLeftToRight();
|
||||||
|
boolean isMacStyle = isMacStyle();
|
||||||
|
int macStyleButtonsWidth = isMacStyle ? getMacStyleButtonsWidth() : 0;
|
||||||
|
|
||||||
// paint background
|
// paint background
|
||||||
g2.setColor( getBackground( enabled ) );
|
g2.setColor( getBackground( enabled ) );
|
||||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
FlatUIUtils.paintComponentBackground( g2, ltr ? 0 : macStyleButtonsWidth, 0, width - macStyleButtonsWidth, height, focusWidth, arc );
|
||||||
|
|
||||||
// paint button background and separator
|
// paint button background and separator
|
||||||
boolean paintButton = !"none".equals( buttonStyle );
|
boolean paintButton = !"none".equals( buttonStyle );
|
||||||
@@ -386,13 +407,35 @@ public class FlatSpinnerUI
|
|||||||
Component button = (handler.nextButton != null) ? handler.nextButton : handler.previousButton;
|
Component button = (handler.nextButton != null) ? handler.nextButton : handler.previousButton;
|
||||||
int arrowX = button.getX();
|
int arrowX = button.getX();
|
||||||
int arrowWidth = button.getWidth();
|
int arrowWidth = button.getWidth();
|
||||||
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
|
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
||||||
|
|
||||||
|
if( isMacStyle ) {
|
||||||
|
Insets insets = spinner.getInsets();
|
||||||
|
int lineWidth = Math.round( FlatUIUtils.getBorderLineWidth( spinner ) );
|
||||||
|
int bx = arrowX;
|
||||||
|
int by = insets.top - lineWidth;
|
||||||
|
int bw = arrowWidth;
|
||||||
|
int bh = height - insets.top - insets.bottom + (lineWidth * 2);
|
||||||
|
float lw = scale( buttonSeparatorWidth );
|
||||||
|
|
||||||
|
// buttons border
|
||||||
|
FlatUIUtils.paintOutlinedComponent( g2, bx, by, bw, bh,
|
||||||
|
0, 0, 0, lw, scale( 12 ),
|
||||||
|
null, separatorColor, buttonBackground );
|
||||||
|
|
||||||
|
// separator between buttons
|
||||||
|
if( separatorColor != null ) {
|
||||||
|
int thickness = scale( 1 );
|
||||||
|
g2.setColor( separatorColor );
|
||||||
|
g2.fill( new Rectangle2D.Float( bx + lw, by + ((bh - thickness) / 2f),
|
||||||
|
bw - (lw * 2), thickness ) );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// paint arrow buttons background
|
// paint arrow buttons background
|
||||||
if( enabled && buttonBackground != null ) {
|
if( enabled && buttonBackground != null ) {
|
||||||
g2.setColor( buttonBackground );
|
g2.setColor( buttonBackground );
|
||||||
Shape oldClip = g2.getClip();
|
Shape oldClip = g2.getClip();
|
||||||
if( isLeftToRight )
|
if( ltr )
|
||||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||||
else
|
else
|
||||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||||
@@ -401,20 +444,33 @@ public class FlatSpinnerUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// paint vertical line between value and arrow buttons
|
// paint vertical line between value and arrow buttons
|
||||||
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
|
||||||
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
||||||
g2.setColor( separatorColor );
|
g2.setColor( separatorColor );
|
||||||
float lw = scale( buttonSeparatorWidth );
|
float lw = scale( buttonSeparatorWidth );
|
||||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
float lx = ltr ? arrowX : arrowX + arrowWidth - lw;
|
||||||
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
|
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
paint( g, c );
|
paint( g, c );
|
||||||
|
|
||||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isMacStyle() {
|
||||||
|
return "mac".equals( buttonStyle );
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMacStyleButtonsWidth() {
|
||||||
|
return (handler.nextButton != null || handler.previousButton != null)
|
||||||
|
? scale( MAC_STEPPER_GAP ) + scale( MAC_STEPPER_WIDTH )
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int MAC_STEPPER_WIDTH = 15;
|
||||||
|
private static final int MAC_STEPPER_GAP = 3;
|
||||||
|
|
||||||
//---- class Handler ------------------------------------------------------
|
//---- class Handler ------------------------------------------------------
|
||||||
|
|
||||||
private class Handler
|
private class Handler
|
||||||
@@ -471,6 +527,7 @@ public class FlatSpinnerUI
|
|||||||
Insets insets = parent.getInsets();
|
Insets insets = parent.getInsets();
|
||||||
Rectangle r = FlatUIUtils.subtractInsets( new Rectangle( size ), insets );
|
Rectangle r = FlatUIUtils.subtractInsets( new Rectangle( size ), insets );
|
||||||
|
|
||||||
|
// editor gets all space if there are no buttons
|
||||||
if( nextButton == null && previousButton == null ) {
|
if( nextButton == null && previousButton == null ) {
|
||||||
if( editor != null )
|
if( editor != null )
|
||||||
editor.setBounds( r );
|
editor.setBounds( r );
|
||||||
@@ -486,20 +543,36 @@ public class FlatSpinnerUI
|
|||||||
int minButtonWidth = (maxButtonWidth * 3) / 4;
|
int minButtonWidth = (maxButtonWidth * 3) / 4;
|
||||||
|
|
||||||
// make button area square (except if width is limited)
|
// make button area square (except if width is limited)
|
||||||
int buttonsWidth = Math.min( Math.max( buttonsRect.height, minButtonWidth ), maxButtonWidth );
|
boolean isMacStyle = isMacStyle();
|
||||||
buttonsRect.width = buttonsWidth;
|
int buttonsGap = isMacStyle ? scale( MAC_STEPPER_GAP ) : 0;
|
||||||
|
int prefButtonWidth = isMacStyle ? scale( MAC_STEPPER_WIDTH ) : buttonsRect.height;
|
||||||
|
int buttonsWidth = Math.min( Math.max( prefButtonWidth, minButtonWidth ), maxButtonWidth );
|
||||||
|
|
||||||
if( parent.getComponentOrientation().isLeftToRight() ) {
|
// update editor and buttons bounds
|
||||||
editorRect.width -= buttonsWidth;
|
buttonsRect.width = buttonsWidth;
|
||||||
buttonsRect.x += editorRect.width;
|
editorRect.width -= buttonsWidth + buttonsGap;
|
||||||
} else {
|
boolean ltr = parent.getComponentOrientation().isLeftToRight();
|
||||||
editorRect.x += buttonsWidth;
|
if( ltr )
|
||||||
editorRect.width -= buttonsWidth;
|
buttonsRect.x += editorRect.width + buttonsGap;
|
||||||
|
else
|
||||||
|
editorRect.x += buttonsWidth + buttonsGap;
|
||||||
|
|
||||||
|
// in mac button style increase buttons height and move to the right
|
||||||
|
// for exact alignment with border
|
||||||
|
if( isMacStyle ) {
|
||||||
|
int lineWidth = Math.round( FlatUIUtils.getBorderLineWidth( spinner ) );
|
||||||
|
if( lineWidth > 0 ) {
|
||||||
|
buttonsRect.x += ltr ? lineWidth : -lineWidth;
|
||||||
|
buttonsRect.y -= lineWidth;
|
||||||
|
buttonsRect.height += lineWidth * 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set editor bounds
|
||||||
if( editor != null )
|
if( editor != null )
|
||||||
editor.setBounds( editorRect );
|
editor.setBounds( editorRect );
|
||||||
|
|
||||||
|
// set buttons bounds
|
||||||
int nextHeight = (buttonsRect.height / 2) + (buttonsRect.height % 2); // round up
|
int nextHeight = (buttonsRect.height / 2) + (buttonsRect.height % 2); // round up
|
||||||
if( nextButton != null )
|
if( nextButton != null )
|
||||||
nextButton.setBounds( buttonsRect.x, buttonsRect.y, buttonsRect.width, nextHeight );
|
nextButton.setBounds( buttonsRect.x, buttonsRect.y, buttonsRect.width, nextHeight );
|
||||||
|
|||||||
@@ -128,12 +128,14 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*
|
*
|
||||||
* @uiDefault TabbedPane.disabledForeground Color
|
* @uiDefault TabbedPane.disabledForeground Color
|
||||||
* @uiDefault TabbedPane.selectedBackground Color optional
|
* @uiDefault TabbedPane.selectedBackground Color optional
|
||||||
* @uiDefault TabbedPane.selectedForeground Color
|
* @uiDefault TabbedPane.selectedForeground Color optional
|
||||||
* @uiDefault TabbedPane.underlineColor Color
|
* @uiDefault TabbedPane.underlineColor Color
|
||||||
* @uiDefault TabbedPane.inactiveUnderlineColor Color
|
* @uiDefault TabbedPane.inactiveUnderlineColor Color
|
||||||
* @uiDefault TabbedPane.disabledUnderlineColor Color
|
* @uiDefault TabbedPane.disabledUnderlineColor Color
|
||||||
* @uiDefault TabbedPane.hoverColor Color
|
* @uiDefault TabbedPane.hoverColor Color optional
|
||||||
* @uiDefault TabbedPane.focusColor Color
|
* @uiDefault TabbedPane.hoverForeground Color optional
|
||||||
|
* @uiDefault TabbedPane.focusColor Color optional
|
||||||
|
* @uiDefault TabbedPane.focusForeground Color optional
|
||||||
* @uiDefault TabbedPane.tabSeparatorColor Color optional; defaults to TabbedPane.contentAreaColor
|
* @uiDefault TabbedPane.tabSeparatorColor Color optional; defaults to TabbedPane.contentAreaColor
|
||||||
* @uiDefault TabbedPane.contentAreaColor Color
|
* @uiDefault TabbedPane.contentAreaColor Color
|
||||||
* @uiDefault TabbedPane.minimumTabWidth int optional
|
* @uiDefault TabbedPane.minimumTabWidth int optional
|
||||||
@@ -205,7 +207,9 @@ public class FlatTabbedPaneUI
|
|||||||
/** @since 2.2 */ @Styleable protected Color inactiveUnderlineColor;
|
/** @since 2.2 */ @Styleable protected Color inactiveUnderlineColor;
|
||||||
@Styleable protected Color disabledUnderlineColor;
|
@Styleable protected Color disabledUnderlineColor;
|
||||||
@Styleable protected Color hoverColor;
|
@Styleable protected Color hoverColor;
|
||||||
|
/** @since 3.1 */ @Styleable protected Color hoverForeground;
|
||||||
@Styleable protected Color focusColor;
|
@Styleable protected Color focusColor;
|
||||||
|
/** @since 3.1 */ @Styleable protected Color focusForeground;
|
||||||
@Styleable protected Color tabSeparatorColor;
|
@Styleable protected Color tabSeparatorColor;
|
||||||
@Styleable protected Color contentAreaColor;
|
@Styleable protected Color contentAreaColor;
|
||||||
|
|
||||||
@@ -328,7 +332,9 @@ public class FlatTabbedPaneUI
|
|||||||
inactiveUnderlineColor = FlatUIUtils.getUIColor( "TabbedPane.inactiveUnderlineColor", underlineColor );
|
inactiveUnderlineColor = FlatUIUtils.getUIColor( "TabbedPane.inactiveUnderlineColor", underlineColor );
|
||||||
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
|
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
|
||||||
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
|
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
|
||||||
|
hoverForeground = UIManager.getColor( "TabbedPane.hoverForeground" );
|
||||||
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
|
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
|
||||||
|
focusForeground = UIManager.getColor( "TabbedPane.focusForeground" );
|
||||||
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
|
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
|
||||||
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
|
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
|
||||||
|
|
||||||
@@ -397,7 +403,9 @@ public class FlatTabbedPaneUI
|
|||||||
inactiveUnderlineColor = null;
|
inactiveUnderlineColor = null;
|
||||||
disabledUnderlineColor = null;
|
disabledUnderlineColor = null;
|
||||||
hoverColor = null;
|
hoverColor = null;
|
||||||
|
hoverForeground = null;
|
||||||
focusColor = null;
|
focusColor = null;
|
||||||
|
focusForeground = null;
|
||||||
tabSeparatorColor = null;
|
tabSeparatorColor = null;
|
||||||
contentAreaColor = null;
|
contentAreaColor = null;
|
||||||
closeIcon = null;
|
closeIcon = null;
|
||||||
@@ -1141,22 +1149,37 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// plain text
|
// plain text
|
||||||
Color color;
|
|
||||||
if( tabPane.isEnabled() && tabPane.isEnabledAt( tabIndex ) ) {
|
|
||||||
color = tabPane.getForegroundAt( tabIndex );
|
|
||||||
if( isSelected && selectedForeground != null && color == tabPane.getForeground() )
|
|
||||||
color = selectedForeground;
|
|
||||||
} else
|
|
||||||
color = disabledForeground;
|
|
||||||
|
|
||||||
int mnemIndex = FlatLaf.isShowMnemonics() ? tabPane.getDisplayedMnemonicIndexAt( tabIndex ) : -1;
|
int mnemIndex = FlatLaf.isShowMnemonics() ? tabPane.getDisplayedMnemonicIndexAt( tabIndex ) : -1;
|
||||||
|
g.setColor( getTabForeground( tabPlacement, tabIndex, isSelected ) );
|
||||||
g.setColor( color );
|
|
||||||
FlatUIUtils.drawStringUnderlineCharAt( tabPane, g, title, mnemIndex,
|
FlatUIUtils.drawStringUnderlineCharAt( tabPane, g, title, mnemIndex,
|
||||||
textRect.x, textRect.y + metrics.getAscent() );
|
textRect.x, textRect.y + metrics.getAscent() );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.1 */
|
||||||
|
protected Color getTabForeground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||||
|
// tabbed pane or tab is disabled
|
||||||
|
if( !tabPane.isEnabled() || !tabPane.isEnabledAt( tabIndex ) )
|
||||||
|
return disabledForeground;
|
||||||
|
|
||||||
|
// hover
|
||||||
|
if( hoverForeground != null && getRolloverTab() == tabIndex )
|
||||||
|
return hoverForeground;
|
||||||
|
|
||||||
|
// tab foreground (if set)
|
||||||
|
Color foreground = tabPane.getForegroundAt( tabIndex );
|
||||||
|
if( foreground != tabPane.getForeground() )
|
||||||
|
return foreground;
|
||||||
|
|
||||||
|
// focused and selected
|
||||||
|
if( focusForeground != null && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane ) )
|
||||||
|
return focusForeground;
|
||||||
|
if( selectedForeground != null && isSelected )
|
||||||
|
return selectedForeground;
|
||||||
|
|
||||||
|
return foreground;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintTabBackground( Graphics g, int tabPlacement, int tabIndex,
|
protected void paintTabBackground( Graphics g, int tabPlacement, int tabIndex,
|
||||||
int x, int y, int w, int h, boolean isSelected )
|
int x, int y, int w, int h, boolean isSelected )
|
||||||
@@ -1169,14 +1192,27 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected Color getTabBackground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
protected Color getTabBackground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||||
boolean enabled = tabPane.isEnabled();
|
Color background = tabPane.getBackgroundAt( tabIndex );
|
||||||
return enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
|
||||||
? hoverColor
|
// tabbed pane or tab is disabled
|
||||||
: (enabled && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane )
|
if( !tabPane.isEnabled() || !tabPane.isEnabledAt( tabIndex ) )
|
||||||
? focusColor
|
return background;
|
||||||
: (selectedBackground != null && enabled && isSelected
|
|
||||||
? selectedBackground
|
// hover
|
||||||
: tabPane.getBackgroundAt( tabIndex )));
|
if( hoverColor != null && getRolloverTab() == tabIndex )
|
||||||
|
return hoverColor;
|
||||||
|
|
||||||
|
// tab background (if set)
|
||||||
|
if( background != tabPane.getBackground() )
|
||||||
|
return background;
|
||||||
|
|
||||||
|
// focused and selected
|
||||||
|
if( focusColor != null && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane ) )
|
||||||
|
return focusColor;
|
||||||
|
if( selectedBackground != null && isSelected )
|
||||||
|
return selectedBackground;
|
||||||
|
|
||||||
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1431,7 +1467,8 @@ public class FlatTabbedPaneUI
|
|||||||
path.append( gap, false );
|
path.append( gap, false );
|
||||||
|
|
||||||
// fill gap in case that the tab is colored (e.g. focused or hover)
|
// fill gap in case that the tab is colored (e.g. focused or hover)
|
||||||
g.setColor( getTabBackground( tabPlacement, selectedIndex, true ) );
|
Color background = getTabBackground( tabPlacement, selectedIndex, true );
|
||||||
|
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||||
((Graphics2D)g).fill( gap );
|
((Graphics2D)g).fill( gap );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.function.Function;
|
|||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.TableUI;
|
import javax.swing.plaf.TableUI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,17 +108,55 @@ public class FlatTableCellBorder
|
|||||||
public static class Focused
|
public static class Focused
|
||||||
extends FlatTableCellBorder
|
extends FlatTableCellBorder
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
if( c != null && c.getClass().getName().equals( "javax.swing.JTable$BooleanRenderer" ) ) {
|
||||||
|
// boolean renderer in JTable does not use Table.focusSelectedCellHighlightBorder
|
||||||
|
// if cell is selected and focused (as DefaultTableCellRenderer does)
|
||||||
|
// --> delegate to Table.focusSelectedCellHighlightBorder
|
||||||
|
// to make FlatLaf "focus indicator border hiding" work
|
||||||
|
JTable table = (JTable) SwingUtilities.getAncestorOfClass( JTable.class, c );
|
||||||
|
if( table != null &&
|
||||||
|
c.getForeground() == table.getSelectionForeground() &&
|
||||||
|
c.getBackground() == table.getSelectionBackground() )
|
||||||
|
{
|
||||||
|
Border border = UIManager.getBorder( "Table.focusSelectedCellHighlightBorder" );
|
||||||
|
if( border != null ) {
|
||||||
|
border.paintBorder( c, g, x, y, width, height );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintBorder( c, g, x, y, width, height );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class Selected -----------------------------------------------------
|
//---- class Selected -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for selected cell that uses margins and paints focus indicator border
|
* Border for selected cell that uses margins and paints focus indicator border.
|
||||||
* if enabled (Table.showCellFocusIndicator=true) or at least one selected cell is editable.
|
* The focus indicator is shown under following conditions:
|
||||||
|
* <ul>
|
||||||
|
* <li>always if enabled via UI property {@code Table.showCellFocusIndicator=true}
|
||||||
|
* <li>for row selection mode if exactly one row is selected and at least one cell in that row is editable
|
||||||
|
* <li>for column selection mode if exactly one column is selected and at least one cell in that column is editable
|
||||||
|
* <li>never for cell selection mode
|
||||||
|
* </ul>
|
||||||
|
* The reason for this logic is to hide the focus indicator when it is not needed,
|
||||||
|
* and only show it when there are editable cells and the user needs to know
|
||||||
|
* which cell is focused to start editing.
|
||||||
|
* <p>
|
||||||
|
* To avoid possible performance issues, checking for editable cells is limited
|
||||||
|
* to {@link #maxCheckCellsEditable}. If there are more cells to check,
|
||||||
|
* the focus indicator is always shown.
|
||||||
*/
|
*/
|
||||||
public static class Selected
|
public static class Selected
|
||||||
extends FlatTableCellBorder
|
extends FlatTableCellBorder
|
||||||
{
|
{
|
||||||
|
/** @since 3.1 */
|
||||||
|
public int maxCheckCellsEditable = 50;
|
||||||
|
|
||||||
@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 ) {
|
||||||
Boolean b = getStyleFromTableUI( c, ui -> ui.showCellFocusIndicator );
|
Boolean b = getStyleFromTableUI( c, ui -> ui.showCellFocusIndicator );
|
||||||
@@ -125,7 +164,7 @@ public class FlatTableCellBorder
|
|||||||
|
|
||||||
if( !showCellFocusIndicator ) {
|
if( !showCellFocusIndicator ) {
|
||||||
JTable table = (JTable) SwingUtilities.getAncestorOfClass( JTable.class, c );
|
JTable table = (JTable) SwingUtilities.getAncestorOfClass( JTable.class, c );
|
||||||
if( table != null && !isSelectionEditable( table ) )
|
if( table != null && !shouldShowCellFocusIndicator( table ) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,30 +172,59 @@ public class FlatTableCellBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether at least one selected cell is editable.
|
* Returns whether focus indicator border should be shown.
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
protected boolean isSelectionEditable( JTable table ) {
|
protected boolean shouldShowCellFocusIndicator( JTable table ) {
|
||||||
if( table.getRowSelectionAllowed() ) {
|
boolean rowSelectionAllowed = table.getRowSelectionAllowed();
|
||||||
|
boolean columnSelectionAllowed = table.getColumnSelectionAllowed();
|
||||||
|
|
||||||
|
// do not show for cell selection mode
|
||||||
|
// (unlikely that user wants edit cell in case that multiple cells are selected;
|
||||||
|
// if only a single cell is selected then it is clear where the focus is)
|
||||||
|
if( rowSelectionAllowed && columnSelectionAllowed )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( rowSelectionAllowed ) {
|
||||||
|
// row selection mode
|
||||||
|
|
||||||
|
// do not show if more than one row is selected
|
||||||
|
// (unlikely that user wants edit cell in this case)
|
||||||
|
if( table.getSelectedRowCount() != 1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// show always if there are too many columns to check for editable
|
||||||
int columnCount = table.getColumnCount();
|
int columnCount = table.getColumnCount();
|
||||||
int[] selectedRows = table.getSelectedRows();
|
if( columnCount > maxCheckCellsEditable )
|
||||||
for( int selectedRow : selectedRows ) {
|
return true;
|
||||||
|
|
||||||
|
// check whether at least one selected cell is editable
|
||||||
|
int selectedRow = table.getSelectedRow();
|
||||||
for( int column = 0; column < columnCount; column++ ) {
|
for( int column = 0; column < columnCount; column++ ) {
|
||||||
if( table.isCellEditable( selectedRow, column ) )
|
if( table.isCellEditable( selectedRow, column ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} else if( columnSelectionAllowed ) {
|
||||||
}
|
// column selection mode
|
||||||
|
|
||||||
if( table.getColumnSelectionAllowed() ) {
|
// do not show if more than one column is selected
|
||||||
|
// (unlikely that user wants edit cell in this case)
|
||||||
|
if( table.getSelectedColumnCount() != 1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// show always if there are too many rows to check for editable
|
||||||
int rowCount = table.getRowCount();
|
int rowCount = table.getRowCount();
|
||||||
int[] selectedColumns = table.getSelectedColumns();
|
if( rowCount > maxCheckCellsEditable )
|
||||||
for( int selectedColumn : selectedColumns ) {
|
return true;
|
||||||
|
|
||||||
|
// check whether at least one selected cell is editable
|
||||||
|
int selectedColumn = table.getSelectedColumn();
|
||||||
for( int row = 0; row < rowCount; row++ ) {
|
for( int row = 0; row < rowCount; row++ ) {
|
||||||
if( table.isCellEditable( row, selectedColumn ) )
|
if( table.isCellEditable( row, selectedColumn ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*
|
*
|
||||||
* <!-- FlatTableHeaderUI -->
|
* <!-- FlatTableHeaderUI -->
|
||||||
*
|
*
|
||||||
|
* @uiDefault TableHeader.hoverBackground Color optional
|
||||||
|
* @uiDefault TableHeader.hoverForeground Color optional
|
||||||
|
* @uiDefault TableHeader.pressedBackground Color optional
|
||||||
|
* @uiDefault TableHeader.pressedForeground Color optional
|
||||||
* @uiDefault TableHeader.bottomSeparatorColor Color
|
* @uiDefault TableHeader.bottomSeparatorColor Color
|
||||||
* @uiDefault TableHeader.height int
|
* @uiDefault TableHeader.height int
|
||||||
* @uiDefault TableHeader.sortIconPosition String right (default), left, top or bottom
|
* @uiDefault TableHeader.sortIconPosition String right (default), left, top or bottom
|
||||||
@@ -81,6 +85,10 @@ public class FlatTableHeaderUI
|
|||||||
extends BasicTableHeaderUI
|
extends BasicTableHeaderUI
|
||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
|
/** @since 3.1 */ @Styleable protected Color hoverBackground;
|
||||||
|
/** @since 3.1 */ @Styleable protected Color hoverForeground;
|
||||||
|
/** @since 3.1 */ @Styleable protected Color pressedBackground;
|
||||||
|
/** @since 3.1 */ @Styleable protected Color pressedForeground;
|
||||||
@Styleable protected Color bottomSeparatorColor;
|
@Styleable protected Color bottomSeparatorColor;
|
||||||
@Styleable protected int height;
|
@Styleable protected int height;
|
||||||
@Styleable(type=String.class) protected int sortIconPosition;
|
@Styleable(type=String.class) protected int sortIconPosition;
|
||||||
@@ -113,6 +121,10 @@ public class FlatTableHeaderUI
|
|||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
|
hoverBackground = UIManager.getColor( "TableHeader.hoverBackground" );
|
||||||
|
hoverForeground = UIManager.getColor( "TableHeader.hoverForeground" );
|
||||||
|
pressedBackground = UIManager.getColor( "TableHeader.pressedBackground" );
|
||||||
|
pressedForeground = UIManager.getColor( "TableHeader.pressedForeground" );
|
||||||
bottomSeparatorColor = UIManager.getColor( "TableHeader.bottomSeparatorColor" );
|
bottomSeparatorColor = UIManager.getColor( "TableHeader.bottomSeparatorColor" );
|
||||||
height = UIManager.getInt( "TableHeader.height" );
|
height = UIManager.getInt( "TableHeader.height" );
|
||||||
sortIconPosition = parseSortIconPosition( UIManager.getString( "TableHeader.sortIconPosition" ) );
|
sortIconPosition = parseSortIconPosition( UIManager.getString( "TableHeader.sortIconPosition" ) );
|
||||||
@@ -122,6 +134,10 @@ public class FlatTableHeaderUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
hoverBackground = null;
|
||||||
|
hoverForeground = null;
|
||||||
|
pressedBackground = null;
|
||||||
|
pressedForeground = null;
|
||||||
bottomSeparatorColor = null;
|
bottomSeparatorColor = null;
|
||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
@@ -211,6 +227,12 @@ public class FlatTableHeaderUI
|
|||||||
return super.getRolloverColumn();
|
return super.getRolloverColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void rolloverColumnUpdated( int oldColumn, int newColumn ) {
|
||||||
|
header.repaint( header.getHeaderRect( oldColumn ) );
|
||||||
|
header.repaint( header.getHeaderRect( newColumn ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
fixDraggedAndResizingColumns( header );
|
fixDraggedAndResizingColumns( header );
|
||||||
@@ -243,21 +265,16 @@ public class FlatTableHeaderUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// temporary use own default renderer if necessary
|
// temporary use own default renderer
|
||||||
FlatTableCellHeaderRenderer sortIconRenderer = null;
|
FlatTableCellHeaderRenderer tempRenderer = new FlatTableCellHeaderRenderer( header.getDefaultRenderer() );
|
||||||
if( sortIconPosition != SwingConstants.RIGHT ) {
|
header.setDefaultRenderer( tempRenderer );
|
||||||
sortIconRenderer = new FlatTableCellHeaderRenderer( header.getDefaultRenderer() );
|
|
||||||
header.setDefaultRenderer( sortIconRenderer );
|
|
||||||
}
|
|
||||||
|
|
||||||
// paint header
|
// paint header
|
||||||
super.paint( g, c );
|
super.paint( g, c );
|
||||||
|
|
||||||
// restore default renderer
|
// restore default renderer
|
||||||
if( sortIconRenderer != null ) {
|
tempRenderer.reset();
|
||||||
sortIconRenderer.reset();
|
header.setDefaultRenderer( tempRenderer.delegate );
|
||||||
header.setDefaultRenderer( sortIconRenderer.delegate );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSystemDefaultRenderer( Object headerRenderer ) {
|
private boolean isSystemDefaultRenderer( Object headerRenderer ) {
|
||||||
@@ -318,8 +335,8 @@ public class FlatTableHeaderUI
|
|||||||
//---- class FlatTableCellHeaderRenderer ----------------------------------
|
//---- class FlatTableCellHeaderRenderer ----------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A delegating header renderer that is only used to paint sort arrows at
|
* A delegating header renderer that is only used to paint hover and pressed
|
||||||
* top, bottom or left position.
|
* background/foreground and to paint sort arrows at top, bottom or left position.
|
||||||
*/
|
*/
|
||||||
private class FlatTableCellHeaderRenderer
|
private class FlatTableCellHeaderRenderer
|
||||||
implements TableCellRenderer, Border, UIResource
|
implements TableCellRenderer, Border, UIResource
|
||||||
@@ -327,6 +344,9 @@ public class FlatTableHeaderUI
|
|||||||
private final TableCellRenderer delegate;
|
private final TableCellRenderer delegate;
|
||||||
|
|
||||||
private JLabel l;
|
private JLabel l;
|
||||||
|
private Color oldBackground;
|
||||||
|
private Color oldForeground;
|
||||||
|
private Boolean oldOpaque;
|
||||||
private int oldHorizontalTextPosition = -1;
|
private int oldHorizontalTextPosition = -1;
|
||||||
private Border origBorder;
|
private Border origBorder;
|
||||||
private Icon sortIcon;
|
private Icon sortIcon;
|
||||||
@@ -345,11 +365,38 @@ public class FlatTableHeaderUI
|
|||||||
|
|
||||||
l = (JLabel) c;
|
l = (JLabel) c;
|
||||||
|
|
||||||
|
// hover and pressed background/foreground
|
||||||
|
TableColumn draggedColumn = header.getDraggedColumn();
|
||||||
|
Color background = null;
|
||||||
|
Color foreground = null;
|
||||||
|
if( draggedColumn != null && header.getTable().convertColumnIndexToView( draggedColumn.getModelIndex() ) == column ) {
|
||||||
|
background = pressedBackground;
|
||||||
|
foreground = pressedForeground;
|
||||||
|
} else if( getRolloverColumn() == column ) {
|
||||||
|
background = hoverBackground;
|
||||||
|
foreground = hoverForeground;
|
||||||
|
}
|
||||||
|
if( background != null ) {
|
||||||
|
if( oldBackground == null )
|
||||||
|
oldBackground = l.getBackground();
|
||||||
|
if( oldOpaque == null )
|
||||||
|
oldOpaque = l.isOpaque();
|
||||||
|
l.setBackground( FlatUIUtils.deriveColor( background, header.getBackground() ) );
|
||||||
|
l.setOpaque( true );
|
||||||
|
}
|
||||||
|
if( foreground != null ) {
|
||||||
|
if( oldForeground == null )
|
||||||
|
oldForeground = l.getForeground();
|
||||||
|
l.setForeground( FlatUIUtils.deriveColor( foreground, header.getForeground() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort icon
|
||||||
if( sortIconPosition == SwingConstants.LEFT ) {
|
if( sortIconPosition == SwingConstants.LEFT ) {
|
||||||
|
// left
|
||||||
if( oldHorizontalTextPosition < 0 )
|
if( oldHorizontalTextPosition < 0 )
|
||||||
oldHorizontalTextPosition = l.getHorizontalTextPosition();
|
oldHorizontalTextPosition = l.getHorizontalTextPosition();
|
||||||
l.setHorizontalTextPosition( SwingConstants.RIGHT );
|
l.setHorizontalTextPosition( SwingConstants.RIGHT );
|
||||||
} else {
|
} else if( sortIconPosition == SwingConstants.TOP || sortIconPosition == SwingConstants.BOTTOM ) {
|
||||||
// top or bottom
|
// top or bottom
|
||||||
sortIcon = l.getIcon();
|
sortIcon = l.getIcon();
|
||||||
origBorder = l.getBorder();
|
origBorder = l.getBorder();
|
||||||
@@ -361,7 +408,16 @@ public class FlatTableHeaderUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
if( l != null && sortIconPosition == SwingConstants.LEFT && oldHorizontalTextPosition >= 0 )
|
if( l == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( oldBackground != null )
|
||||||
|
l.setBackground( oldBackground );
|
||||||
|
if( oldForeground != null )
|
||||||
|
l.setForeground( oldForeground );
|
||||||
|
if( oldOpaque != null )
|
||||||
|
l.setOpaque( oldOpaque );
|
||||||
|
if( oldHorizontalTextPosition >= 0 )
|
||||||
l.setHorizontalTextPosition( oldHorizontalTextPosition );
|
l.setHorizontalTextPosition( oldHorizontalTextPosition );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
public class FlatTitlePane
|
public class FlatTitlePane
|
||||||
extends JComponent
|
extends JComponent
|
||||||
{
|
{
|
||||||
|
private static final String KEY_DEBUG_SHOW_RECTANGLES = "FlatLaf.debug.titlebar.showRectangles";
|
||||||
|
|
||||||
/** @since 2.5 */ protected final Font titleFont = UIManager.getFont( "TitlePane.font" );
|
/** @since 2.5 */ protected final Font titleFont = UIManager.getFont( "TitlePane.font" );
|
||||||
protected final Color activeBackground = UIManager.getColor( "TitlePane.background" );
|
protected final Color activeBackground = UIManager.getColor( "TitlePane.background" );
|
||||||
protected final Color inactiveBackground = UIManager.getColor( "TitlePane.inactiveBackground" );
|
protected final Color inactiveBackground = UIManager.getColor( "TitlePane.inactiveBackground" );
|
||||||
@@ -354,16 +356,12 @@ public class FlatTitlePane
|
|||||||
if( window == null || rootPane.getWindowDecorationStyle() != JRootPane.FRAME )
|
if( window == null || rootPane.getWindowDecorationStyle() != JRootPane.FRAME )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
updateVisibility();
|
||||||
|
|
||||||
if( window instanceof Frame ) {
|
if( window instanceof Frame ) {
|
||||||
Frame frame = (Frame) window;
|
Frame frame = (Frame) window;
|
||||||
boolean resizable = frame.isResizable();
|
|
||||||
boolean maximized = ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0);
|
|
||||||
|
|
||||||
iconifyButton.setVisible( true );
|
if( isWindowMaximized() &&
|
||||||
maximizeButton.setVisible( resizable && !maximized );
|
|
||||||
restoreButton.setVisible( resizable && maximized );
|
|
||||||
|
|
||||||
if( maximized &&
|
|
||||||
!(SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window )) &&
|
!(SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window )) &&
|
||||||
rootPane.getClientProperty( "_flatlaf.maximizedBoundsUpToDate" ) == null )
|
rootPane.getClientProperty( "_flatlaf.maximizedBoundsUpToDate" ) == null )
|
||||||
{
|
{
|
||||||
@@ -383,14 +381,27 @@ public class FlatTitlePane
|
|||||||
frame.setExtendedState( oldExtendedState );
|
frame.setExtendedState( oldExtendedState );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
protected void updateVisibility() {
|
||||||
|
titleLabel.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_TITLE, true ) );
|
||||||
|
closeButton.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_CLOSE, true ) );
|
||||||
|
|
||||||
|
if( window instanceof Frame ) {
|
||||||
|
Frame frame = (Frame) window;
|
||||||
|
boolean maximizable = frame.isResizable() && clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_MAXIMIZE, true );
|
||||||
|
boolean maximized = isWindowMaximized();
|
||||||
|
|
||||||
|
iconifyButton.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICONIFFY, true ) );
|
||||||
|
maximizeButton.setVisible( maximizable && !maximized );
|
||||||
|
restoreButton.setVisible( maximizable && maximized );
|
||||||
} else {
|
} else {
|
||||||
// hide buttons because they are only supported in frames
|
// hide buttons because they are only supported in frames
|
||||||
iconifyButton.setVisible( false );
|
iconifyButton.setVisible( false );
|
||||||
maximizeButton.setVisible( false );
|
maximizeButton.setVisible( false );
|
||||||
restoreButton.setVisible( false );
|
restoreButton.setVisible( false );
|
||||||
|
|
||||||
revalidate();
|
|
||||||
repaint();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,11 +577,13 @@ public class FlatTitlePane
|
|||||||
doLayout();
|
doLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*debug
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g ) {
|
public void paint( Graphics g ) {
|
||||||
super.paint( g );
|
super.paint( g );
|
||||||
|
|
||||||
|
if( !UIManager.getBoolean( KEY_DEBUG_SHOW_RECTANGLES ) )
|
||||||
|
return;
|
||||||
|
|
||||||
if( debugTitleBarHeight > 0 ) {
|
if( debugTitleBarHeight > 0 ) {
|
||||||
g.setColor( Color.green );
|
g.setColor( Color.green );
|
||||||
g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight );
|
g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight );
|
||||||
@@ -594,7 +607,6 @@ public class FlatTitlePane
|
|||||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||||
}
|
}
|
||||||
debug*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintComponent( Graphics g ) {
|
protected void paintComponent( Graphics g ) {
|
||||||
@@ -630,7 +642,10 @@ debug*/
|
|||||||
|
|
||||||
/** @since 2.4 */
|
/** @since 2.4 */
|
||||||
protected boolean isWindowMaximized() {
|
protected boolean isWindowMaximized() {
|
||||||
return window instanceof Frame && (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
// Windows and macOS use always MAXIMIZED_BOTH.
|
||||||
|
// Only Linux uses MAXIMIZED_VERT and MAXIMIZED_HORIZ (when dragging window to left or right edge).
|
||||||
|
// (searched jdk source code)
|
||||||
|
return window instanceof Frame && (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -648,8 +663,30 @@ debug*/
|
|||||||
rootPane.putClientProperty( "_flatlaf.maximizedBoundsUpToDate", true );
|
rootPane.putClientProperty( "_flatlaf.maximizedBoundsUpToDate", true );
|
||||||
|
|
||||||
// maximize window
|
// maximize window
|
||||||
if( !FlatNativeWindowBorder.showWindow( frame, FlatNativeWindowBorder.Provider.SW_MAXIMIZE ) )
|
if( !FlatNativeWindowBorder.showWindow( frame, FlatNativeWindowBorder.Provider.SW_MAXIMIZE ) ) {
|
||||||
frame.setExtendedState( frame.getExtendedState() | Frame.MAXIMIZED_BOTH );
|
int oldState = frame.getExtendedState();
|
||||||
|
int newState = oldState | Frame.MAXIMIZED_BOTH;
|
||||||
|
|
||||||
|
if( SystemInfo.isLinux ) {
|
||||||
|
// Linux supports vertical and horizontal maximization:
|
||||||
|
// - dragging a window to left or right edge of screen vertically maximizes
|
||||||
|
// the window to the left or right half of the screen
|
||||||
|
// - don't know whether user can do horizontal maximization
|
||||||
|
// (Windows and macOS use only MAXIMIZED_BOTH)
|
||||||
|
//
|
||||||
|
// If a window is maximized vertically or horizontally (but not both),
|
||||||
|
// then Frame.setExtendedState() behaves not as expected on Linux.
|
||||||
|
// E.g. if window state is MAXIMIZED_VERT, calling setExtendedState(MAXIMIZED_BOTH)
|
||||||
|
// changes state to MAXIMIZED_HORIZ. But calling setExtendedState(MAXIMIZED_HORIZ)
|
||||||
|
// changes state from MAXIMIZED_VERT to MAXIMIZED_BOTH.
|
||||||
|
// Seems to be a bug in sun.awt.X11.XNETProtocol.requestState(),
|
||||||
|
// which does some strange state XOR-ing...
|
||||||
|
if( (oldState & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_VERT )
|
||||||
|
newState = oldState & ~Frame.MAXIMIZED_BOTH | Frame.MAXIMIZED_HORIZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.setExtendedState( newState );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateMaximizedBounds() {
|
protected void updateMaximizedBounds() {
|
||||||
@@ -753,8 +790,7 @@ debug*/
|
|||||||
if( !(window instanceof Frame) || !((Frame)window).isResizable() )
|
if( !(window instanceof Frame) || !((Frame)window).isResizable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Frame frame = (Frame) window;
|
if( isWindowMaximized() )
|
||||||
if( (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0 )
|
|
||||||
restore();
|
restore();
|
||||||
else
|
else
|
||||||
maximize();
|
maximize();
|
||||||
@@ -923,15 +959,14 @@ debug*/
|
|||||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
||||||
hitTestSpots, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
hitTestSpots, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||||
|
|
||||||
/*debug
|
|
||||||
debugTitleBarHeight = titleBarHeight;
|
debugTitleBarHeight = titleBarHeight;
|
||||||
debugHitTestSpots = hitTestSpots;
|
debugHitTestSpots = hitTestSpots;
|
||||||
debugAppIconBounds = appIconBounds;
|
debugAppIconBounds = appIconBounds;
|
||||||
debugMinimizeButtonBounds = minimizeButtonBounds;
|
debugMinimizeButtonBounds = minimizeButtonBounds;
|
||||||
debugMaximizeButtonBounds = maximizeButtonBounds;
|
debugMaximizeButtonBounds = maximizeButtonBounds;
|
||||||
debugCloseButtonBounds = closeButtonBounds;
|
debugCloseButtonBounds = closeButtonBounds;
|
||||||
|
if( UIManager.getBoolean( KEY_DEBUG_SHOW_RECTANGLES ) )
|
||||||
repaint();
|
repaint();
|
||||||
debug*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Rectangle boundsInWindow( JComponent c ) {
|
private Rectangle boundsInWindow( JComponent c ) {
|
||||||
@@ -950,14 +985,12 @@ debug*/
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*debug
|
|
||||||
private int debugTitleBarHeight;
|
private int debugTitleBarHeight;
|
||||||
private List<Rectangle> debugHitTestSpots;
|
private List<Rectangle> debugHitTestSpots;
|
||||||
private Rectangle debugAppIconBounds;
|
private Rectangle debugAppIconBounds;
|
||||||
private Rectangle debugMinimizeButtonBounds;
|
private Rectangle debugMinimizeButtonBounds;
|
||||||
private Rectangle debugMaximizeButtonBounds;
|
private Rectangle debugMaximizeButtonBounds;
|
||||||
private Rectangle debugCloseButtonBounds;
|
private Rectangle debugCloseButtonBounds;
|
||||||
debug*/
|
|
||||||
|
|
||||||
//---- class FlatTitlePaneBorder ------------------------------------------
|
//---- class FlatTitlePaneBorder ------------------------------------------
|
||||||
|
|
||||||
@@ -1178,6 +1211,13 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowStateChanged( WindowEvent e ) {
|
public void windowStateChanged( WindowEvent e ) {
|
||||||
|
/*debug
|
||||||
|
System.out.println( "state " + e.getOldState() + " -> " + e.getNewState() + " "
|
||||||
|
+ ((e.getNewState() & Frame.MAXIMIZED_HORIZ) != 0 ? " HORIZ" : "")
|
||||||
|
+ ((e.getNewState() & Frame.MAXIMIZED_VERT) != 0 ? " VERT" : "")
|
||||||
|
);
|
||||||
|
debug*/
|
||||||
|
|
||||||
frameStateChanged();
|
frameStateChanged();
|
||||||
updateNativeTitleBarHeightAndHitTestSpots();
|
updateNativeTitleBarHeightAndHitTestSpots();
|
||||||
}
|
}
|
||||||
@@ -1185,7 +1225,7 @@ debug*/
|
|||||||
//---- interface MouseListener ----
|
//---- interface MouseListener ----
|
||||||
|
|
||||||
private Point dragOffset;
|
private Point dragOffset;
|
||||||
private boolean nativeMove;
|
private boolean linuxNativeMove;
|
||||||
private long lastSingleClickWhen;
|
private long lastSingleClickWhen;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1193,7 +1233,7 @@ debug*/
|
|||||||
// on Linux, when using native library, the mouse clicked event
|
// on Linux, when using native library, the mouse clicked event
|
||||||
// is usually not sent and maximize/restore is done in mouse pressed 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 thru for some reason
|
// this check is here for the case that a mouse clicked event comes thru for some reason
|
||||||
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||||
// see comment in mousePressed()
|
// see comment in mousePressed()
|
||||||
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
||||||
lastSingleClickWhen = 0;
|
lastSingleClickWhen = 0;
|
||||||
@@ -1231,7 +1271,7 @@ debug*/
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
dragOffset = SwingUtilities.convertPoint( FlatTitlePane.this, e.getPoint(), window );
|
dragOffset = SwingUtilities.convertPoint( FlatTitlePane.this, e.getPoint(), window );
|
||||||
nativeMove = false;
|
linuxNativeMove = false;
|
||||||
|
|
||||||
// on Linux, move or maximize/restore window
|
// on Linux, move or maximize/restore window
|
||||||
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||||
@@ -1251,7 +1291,7 @@ debug*/
|
|||||||
case 1:
|
case 1:
|
||||||
// move window via _NET_WM_MOVERESIZE message
|
// move window via _NET_WM_MOVERESIZE message
|
||||||
e.consume();
|
e.consume();
|
||||||
nativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
||||||
lastSingleClickWhen = e.getWhen();
|
lastSingleClickWhen = e.getWhen();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1281,7 +1321,7 @@ debug*/
|
|||||||
if( window == null || dragOffset == null )
|
if( window == null || dragOffset == null )
|
||||||
return; // should newer occur
|
return; // should newer occur
|
||||||
|
|
||||||
if( nativeMove )
|
if( linuxNativeMove )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !SwingUtilities.isLeftMouseButton( e ) )
|
if( !SwingUtilities.isLeftMouseButton( e ) )
|
||||||
|
|||||||
@@ -20,15 +20,24 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.FocusTraversalPolicy;
|
import java.awt.FocusTraversalPolicy;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.ContainerEvent;
|
import java.awt.event.ContainerEvent;
|
||||||
import java.awt.event.ContainerListener;
|
import java.awt.event.ContainerListener;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.ButtonModel;
|
||||||
|
import javax.swing.DefaultButtonModel;
|
||||||
import javax.swing.InputMap;
|
import javax.swing.InputMap;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LayoutFocusTraversalPolicy;
|
import javax.swing.LayoutFocusTraversalPolicy;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
@@ -37,6 +46,7 @@ import javax.swing.plaf.basic.BasicToolBarUI;
|
|||||||
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.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JToolBar}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JToolBar}.
|
||||||
@@ -58,6 +68,8 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* @uiDefault ToolBar.focusableButtons boolean
|
* @uiDefault ToolBar.focusableButtons boolean
|
||||||
* @uiDefault ToolBar.arrowKeysOnlyNavigation boolean
|
* @uiDefault ToolBar.arrowKeysOnlyNavigation boolean
|
||||||
* @uiDefault ToolBar.floatable boolean
|
* @uiDefault ToolBar.floatable boolean
|
||||||
|
* @uiDefault ToolBar.hoverButtonGroupArc int
|
||||||
|
* @uiDefault ToolBar.hoverButtonGroupBackground Color
|
||||||
*
|
*
|
||||||
* <!-- FlatToolBarBorder -->
|
* <!-- FlatToolBarBorder -->
|
||||||
*
|
*
|
||||||
@@ -72,6 +84,8 @@ public class FlatToolBarUI
|
|||||||
{
|
{
|
||||||
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
||||||
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
||||||
|
/** @since 3 */ @Styleable protected int hoverButtonGroupArc;
|
||||||
|
/** @since 3 */ @Styleable protected Color hoverButtonGroupBackground;
|
||||||
|
|
||||||
// for FlatToolBarBorder
|
// for FlatToolBarBorder
|
||||||
@Styleable protected Insets borderMargins;
|
@Styleable protected Insets borderMargins;
|
||||||
@@ -119,6 +133,8 @@ public class FlatToolBarUI
|
|||||||
|
|
||||||
focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" );
|
focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" );
|
||||||
arrowKeysOnlyNavigation = UIManager.getBoolean( "ToolBar.arrowKeysOnlyNavigation" );
|
arrowKeysOnlyNavigation = UIManager.getBoolean( "ToolBar.arrowKeysOnlyNavigation" );
|
||||||
|
hoverButtonGroupArc = UIManager.getInt( "ToolBar.hoverButtonGroupArc" );
|
||||||
|
hoverButtonGroupBackground = UIManager.getColor( "ToolBar.hoverButtonGroupBackground" );
|
||||||
|
|
||||||
// floatable
|
// floatable
|
||||||
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
|
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
|
||||||
@@ -132,6 +148,8 @@ public class FlatToolBarUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
hoverButtonGroupBackground = null;
|
||||||
|
|
||||||
if( oldFloatable != null ) {
|
if( oldFloatable != null ) {
|
||||||
toolBar.setFloatable( oldFloatable );
|
toolBar.setFloatable( oldFloatable );
|
||||||
oldFloatable = null;
|
oldFloatable = null;
|
||||||
@@ -329,6 +347,99 @@ public class FlatToolBarUI
|
|||||||
super.setOrientation( orientation );
|
super.setOrientation( orientation );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint( Graphics g, JComponent c ) {
|
||||||
|
super.paint( g, c );
|
||||||
|
|
||||||
|
paintButtonGroup( g );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**@since 3 */
|
||||||
|
protected void paintButtonGroup( Graphics g ) {
|
||||||
|
if( hoverButtonGroupBackground == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find hovered button that is part of a button group
|
||||||
|
ButtonGroup group = null;
|
||||||
|
for( Component b : toolBar.getComponents() ) {
|
||||||
|
if( b instanceof AbstractButton && ((AbstractButton)b).getModel().isRollover() ) {
|
||||||
|
group = getButtonGroup( (AbstractButton) b );
|
||||||
|
if( group != null )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( group == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get bounds of buttons in group
|
||||||
|
ArrayList<Rectangle> rects = new ArrayList<>();
|
||||||
|
Enumeration<AbstractButton> e = group.getElements();
|
||||||
|
while( e.hasMoreElements() ) {
|
||||||
|
AbstractButton gb = e.nextElement();
|
||||||
|
if( gb.getParent() == toolBar )
|
||||||
|
rects.add( gb.getBounds() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort button bounds
|
||||||
|
boolean horizontal = (toolBar.getOrientation() == JToolBar.HORIZONTAL);
|
||||||
|
rects.sort( (r1, r2) -> horizontal ? r1.x - r2.x : r1.y - r2.y );
|
||||||
|
|
||||||
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
g.setColor( FlatUIUtils.deriveColor( hoverButtonGroupBackground, toolBar.getBackground() ) );
|
||||||
|
|
||||||
|
// paint button group hover background
|
||||||
|
int maxSepWidth = UIScale.scale( 10 );
|
||||||
|
Rectangle gr = null;
|
||||||
|
for( Rectangle r : rects ) {
|
||||||
|
if( gr == null ) {
|
||||||
|
// first button
|
||||||
|
gr = r;
|
||||||
|
} else if( horizontal ? (gr.x + gr.width + maxSepWidth >= r.x) : (gr.y + gr.height + maxSepWidth >= r.y) ) {
|
||||||
|
// button joins previous button
|
||||||
|
gr = gr.union( r );
|
||||||
|
} else {
|
||||||
|
// paint group
|
||||||
|
FlatUIUtils.paintComponentBackground( (Graphics2D) g, gr.x, gr.y, gr.width, gr.height, 0, UIScale.scale( hoverButtonGroupArc ) );
|
||||||
|
gr = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( gr != null )
|
||||||
|
FlatUIUtils.paintComponentBackground( (Graphics2D) g, gr.x, gr.y, gr.width, gr.height, 0, UIScale.scale( hoverButtonGroupArc ) );
|
||||||
|
|
||||||
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**@since 3 */
|
||||||
|
protected void repaintButtonGroup( AbstractButton b ) {
|
||||||
|
if( hoverButtonGroupBackground == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
ButtonGroup group = getButtonGroup( b );
|
||||||
|
if( group == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// compute union bounds of all buttons in group (including separators)
|
||||||
|
Rectangle gr = null;
|
||||||
|
Enumeration<AbstractButton> e = group.getElements();
|
||||||
|
while( e.hasMoreElements() ) {
|
||||||
|
AbstractButton gb = e.nextElement();
|
||||||
|
Container parent = gb.getParent();
|
||||||
|
if( parent == toolBar )
|
||||||
|
gr = (gr != null) ? gr.union( gb.getBounds() ) : gb.getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
// repaint button group
|
||||||
|
if( gr != null )
|
||||||
|
toolBar.repaint( gr );
|
||||||
|
}
|
||||||
|
|
||||||
|
private ButtonGroup getButtonGroup( AbstractButton b ) {
|
||||||
|
ButtonModel model = b.getModel();
|
||||||
|
return (model instanceof DefaultButtonModel)
|
||||||
|
? ((DefaultButtonModel)model).getGroup()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,15 +17,19 @@
|
|||||||
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.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.CellRendererPane;
|
import javax.swing.CellRendererPane;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
@@ -36,6 +40,7 @@ import javax.swing.LookAndFeel;
|
|||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.JTree.DropLocation;
|
import javax.swing.JTree.DropLocation;
|
||||||
|
import javax.swing.event.TreeSelectionListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicTreeUI;
|
import javax.swing.plaf.basic.BasicTreeUI;
|
||||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||||
@@ -96,8 +101,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.selectionInsets Insets
|
||||||
|
* @uiDefault Tree.selectionArc int
|
||||||
* @uiDefault Tree.wideSelection boolean
|
* @uiDefault Tree.wideSelection boolean
|
||||||
* @uiDefault Tree.showCellFocusIndicator boolean
|
* @uiDefault Tree.showCellFocusIndicator boolean
|
||||||
|
* @uiDefault Tree.showDefaultIcons boolean
|
||||||
*
|
*
|
||||||
* <!-- FlatTreeExpandedIcon -->
|
* <!-- FlatTreeExpandedIcon -->
|
||||||
*
|
*
|
||||||
@@ -132,8 +140,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 */ @Styleable protected Insets selectionInsets;
|
||||||
|
/** @since 3 */ @Styleable protected int selectionArc;
|
||||||
@Styleable protected boolean wideSelection;
|
@Styleable protected boolean wideSelection;
|
||||||
@Styleable protected boolean showCellFocusIndicator;
|
@Styleable protected boolean showCellFocusIndicator;
|
||||||
|
/** @since 3 */ protected boolean showDefaultIcons;
|
||||||
|
|
||||||
// for icons
|
// for icons
|
||||||
// (needs to be public because icon classes are in another package)
|
// (needs to be public because icon classes are in another package)
|
||||||
@@ -147,6 +158,11 @@ public class FlatTreeUI
|
|||||||
// 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)
|
||||||
/** @since 2 */ @Styleable protected boolean paintSelection = true;
|
/** @since 2 */ @Styleable protected boolean paintSelection = true;
|
||||||
|
|
||||||
|
private Icon defaultLeafIcon;
|
||||||
|
private Icon defaultClosedIcon;
|
||||||
|
private Icon defaultOpenIcon;
|
||||||
|
|
||||||
|
private boolean paintLines;
|
||||||
private Color defaultCellNonSelectionBackground;
|
private Color defaultCellNonSelectionBackground;
|
||||||
private Color defaultSelectionBackground;
|
private Color defaultSelectionBackground;
|
||||||
private Color defaultSelectionForeground;
|
private Color defaultSelectionForeground;
|
||||||
@@ -175,9 +191,17 @@ 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" );
|
||||||
|
selectionInsets = UIManager.getInsets( "Tree.selectionInsets" );
|
||||||
|
selectionArc = UIManager.getInt( "Tree.selectionArc" );
|
||||||
wideSelection = UIManager.getBoolean( "Tree.wideSelection" );
|
wideSelection = UIManager.getBoolean( "Tree.wideSelection" );
|
||||||
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
|
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
|
||||||
|
showDefaultIcons = UIManager.getBoolean( "Tree.showDefaultIcons" );
|
||||||
|
|
||||||
|
defaultLeafIcon = UIManager.getIcon( "Tree.leafIcon" );
|
||||||
|
defaultClosedIcon = UIManager.getIcon( "Tree.closedIcon" );
|
||||||
|
defaultOpenIcon = UIManager.getIcon( "Tree.openIcon" );
|
||||||
|
|
||||||
|
paintLines = UIManager.getBoolean( "Tree.paintLines" );
|
||||||
defaultCellNonSelectionBackground = UIManager.getColor( "Tree.textBackground" );
|
defaultCellNonSelectionBackground = UIManager.getColor( "Tree.textBackground" );
|
||||||
defaultSelectionBackground = selectionBackground;
|
defaultSelectionBackground = selectionBackground;
|
||||||
defaultSelectionForeground = selectionForeground;
|
defaultSelectionForeground = selectionForeground;
|
||||||
@@ -203,6 +227,10 @@ public class FlatTreeUI
|
|||||||
selectionInactiveForeground = null;
|
selectionInactiveForeground = null;
|
||||||
selectionBorderColor = null;
|
selectionBorderColor = null;
|
||||||
|
|
||||||
|
defaultLeafIcon = null;
|
||||||
|
defaultClosedIcon = null;
|
||||||
|
defaultOpenIcon = null;
|
||||||
|
|
||||||
defaultCellNonSelectionBackground = null;
|
defaultCellNonSelectionBackground = null;
|
||||||
defaultSelectionBackground = null;
|
defaultSelectionBackground = null;
|
||||||
defaultSelectionForeground = null;
|
defaultSelectionForeground = null;
|
||||||
@@ -210,6 +238,24 @@ public class FlatTreeUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateRenderer() {
|
||||||
|
super.updateRenderer();
|
||||||
|
|
||||||
|
// remove default leaf/closed/opened icons
|
||||||
|
if( !showDefaultIcons && currentCellRenderer instanceof DefaultTreeCellRenderer ) {
|
||||||
|
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) currentCellRenderer;
|
||||||
|
if( renderer.getLeafIcon() == defaultLeafIcon &&
|
||||||
|
renderer.getClosedIcon() == defaultClosedIcon &&
|
||||||
|
renderer.getOpenIcon() == defaultOpenIcon )
|
||||||
|
{
|
||||||
|
renderer.setLeafIcon( null );
|
||||||
|
renderer.setClosedIcon( null );
|
||||||
|
renderer.setOpenIcon( null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MouseListener createMouseListener() {
|
protected MouseListener createMouseListener() {
|
||||||
return new BasicTreeUI.MouseHandler() {
|
return new BasicTreeUI.MouseHandler() {
|
||||||
@@ -281,6 +327,21 @@ public class FlatTreeUI
|
|||||||
tree.revalidate();
|
tree.revalidate();
|
||||||
tree.repaint();
|
tree.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "enabled":
|
||||||
|
// if default icons are not shown and the renderer is a subclass
|
||||||
|
// of DefaultTreeCellRenderer, then invalidate tree node sizes
|
||||||
|
// because the custom renderer may use an icon for enabled state
|
||||||
|
// but none for disabled state
|
||||||
|
if( !showDefaultIcons &&
|
||||||
|
currentCellRenderer instanceof DefaultTreeCellRenderer &&
|
||||||
|
currentCellRenderer.getClass() != DefaultTreeCellRenderer.class &&
|
||||||
|
treeState != null )
|
||||||
|
{
|
||||||
|
treeState.invalidateSizes();
|
||||||
|
updateSize();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -295,6 +356,34 @@ public class FlatTreeUI
|
|||||||
tree.repaint( 0, r.y, tree.getWidth(), r.height );
|
tree.repaint( 0, r.y, tree.getWidth(), r.height );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TreeSelectionListener createTreeSelectionListener() {
|
||||||
|
TreeSelectionListener superListener = super.createTreeSelectionListener();
|
||||||
|
return e -> {
|
||||||
|
superListener.valueChanged( e );
|
||||||
|
|
||||||
|
// for united rounded selection, repaint parts of the rows that adjoin to the changed rows
|
||||||
|
TreePath[] changedPaths;
|
||||||
|
if( useUnitedRoundedSelection() &&
|
||||||
|
tree.getSelectionCount() > 1 &&
|
||||||
|
(changedPaths = e.getPaths()) != null )
|
||||||
|
{
|
||||||
|
if( changedPaths.length > 4 ) {
|
||||||
|
// same is done in BasicTreeUI.Handler.valueChanged()
|
||||||
|
tree.repaint();
|
||||||
|
} else {
|
||||||
|
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||||
|
|
||||||
|
for( TreePath path : changedPaths ) {
|
||||||
|
Rectangle r = getPathBounds( tree, path );
|
||||||
|
if( r != null )
|
||||||
|
tree.repaint( r.x, r.y - arc, r.width, r.height + (arc * 2) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Rectangle getPathBounds( JTree tree, TreePath path ) {
|
public Rectangle getPathBounds( JTree tree, TreePath path ) {
|
||||||
Rectangle bounds = super.getPathBounds( tree, path );
|
Rectangle bounds = super.getPathBounds( tree, path );
|
||||||
@@ -346,8 +435,127 @@ public class FlatTreeUI
|
|||||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint( Graphics g, JComponent c ) {
|
||||||
|
if( treeState == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// use clip bounds to limit painting to needed rows
|
||||||
|
Rectangle clipBounds = g.getClipBounds();
|
||||||
|
TreePath firstPath = getClosestPathForLocation( tree, 0, clipBounds.y );
|
||||||
|
Enumeration<TreePath> visiblePaths = treeState.getVisiblePathsFrom( firstPath );
|
||||||
|
|
||||||
|
if( visiblePaths != null ) {
|
||||||
|
Insets insets = tree.getInsets();
|
||||||
|
|
||||||
|
HashSet<TreePath> verticalLinePaths = paintLines ? new HashSet<>() : null;
|
||||||
|
ArrayList<Runnable> paintLinesLater = paintLines ? new ArrayList<>() : null;
|
||||||
|
ArrayList<Runnable> paintExpandControlsLater = paintLines ? new ArrayList<>() : null;
|
||||||
|
|
||||||
|
// add parents for later painting of vertical lines
|
||||||
|
if( paintLines ) {
|
||||||
|
for( TreePath path = firstPath.getParentPath(); path != null; path = path.getParentPath() )
|
||||||
|
verticalLinePaths.add( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle boundsBuffer = new Rectangle();
|
||||||
|
boolean rootVisible = isRootVisible();
|
||||||
|
int row = treeState.getRowForPath( firstPath );
|
||||||
|
boolean leftToRight = tree.getComponentOrientation().isLeftToRight();
|
||||||
|
int treeWidth = tree.getWidth();
|
||||||
|
|
||||||
|
// iterate over visible rows and paint rows, expand control and lines
|
||||||
|
while( visiblePaths.hasMoreElements() ) {
|
||||||
|
TreePath path = visiblePaths.nextElement();
|
||||||
|
if( path == null )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// compute path bounds
|
||||||
|
Rectangle bounds = treeState.getBounds( path, boundsBuffer );
|
||||||
|
if( bounds == null )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// add tree insets to path bounds
|
||||||
|
if( leftToRight )
|
||||||
|
bounds.x += insets.left;
|
||||||
|
else
|
||||||
|
bounds.x = treeWidth - insets.right - (bounds.x + bounds.width);
|
||||||
|
bounds.y += insets.top;
|
||||||
|
|
||||||
|
boolean isLeaf = treeModel.isLeaf( path.getLastPathComponent() );
|
||||||
|
boolean isExpanded = isLeaf ? false : treeState.getExpandedState( path );
|
||||||
|
boolean hasBeenExpanded = isLeaf ? false : tree.hasBeenExpanded( path );
|
||||||
|
|
||||||
|
// paint row (including selection)
|
||||||
|
paintRow( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
||||||
|
|
||||||
|
// collect lines for later painting
|
||||||
|
if( paintLines ) {
|
||||||
|
TreePath parentPath = path.getParentPath();
|
||||||
|
|
||||||
|
// add parent for later painting of vertical lines
|
||||||
|
if( parentPath != null )
|
||||||
|
verticalLinePaths.add( parentPath );
|
||||||
|
|
||||||
|
// paint horizontal line later (for using rendering hints)
|
||||||
|
if( parentPath != null || (rootVisible && row == 0) ) {
|
||||||
|
Rectangle bounds2 = new Rectangle( bounds );
|
||||||
|
int row2 = row;
|
||||||
|
paintLinesLater.add( () -> {
|
||||||
|
paintHorizontalPartOfLeg( g, clipBounds, insets, bounds2, path, row2, isExpanded, hasBeenExpanded, isLeaf );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// paint expand control
|
||||||
|
if( shouldPaintExpandControl( path, row, isExpanded, hasBeenExpanded, isLeaf ) ) {
|
||||||
|
if( paintLines ) {
|
||||||
|
// need to paint after painting lines
|
||||||
|
Rectangle bounds2 = new Rectangle( bounds );
|
||||||
|
int row2 = row;
|
||||||
|
paintExpandControlsLater.add( () -> {
|
||||||
|
paintExpandControl( g, clipBounds, insets, bounds2, path, row2, isExpanded, hasBeenExpanded, isLeaf );
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
paintExpandControl( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bounds.y + bounds.height >= clipBounds.y + clipBounds.height )
|
||||||
|
break;
|
||||||
|
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( paintLines ) {
|
||||||
|
// enable antialiasing for line painting
|
||||||
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
|
||||||
|
// paint horizontal lines
|
||||||
|
for( Runnable r : paintLinesLater )
|
||||||
|
r.run();
|
||||||
|
|
||||||
|
// paint vertical lines
|
||||||
|
g.setColor( Color.green );
|
||||||
|
for( TreePath path : verticalLinePaths )
|
||||||
|
paintVerticalPartOfLeg( g, clipBounds, insets, path );
|
||||||
|
|
||||||
|
// restore rendering hints
|
||||||
|
if( oldRenderingHints != null )
|
||||||
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
|
|
||||||
|
// paint expand controls
|
||||||
|
for( Runnable r : paintExpandControlsLater )
|
||||||
|
r.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paintDropLine( g );
|
||||||
|
|
||||||
|
rendererPane.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as super.paintRow(), but supports wide selection and uses
|
* Similar to super.paintRow(), but supports wide selection and uses
|
||||||
* inactive selection background/foreground if tree is not focused.
|
* inactive selection background/foreground if tree is not focused.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -428,7 +636,7 @@ public class FlatTreeUI
|
|||||||
paintWideSelection( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
paintWideSelection( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
||||||
} else {
|
} else {
|
||||||
// non-wide selection
|
// non-wide selection
|
||||||
paintCellBackground( g, rendererComponent, bounds );
|
paintCellBackground( g, rendererComponent, bounds, row, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is actually not necessary because renderer should always set color
|
// this is actually not necessary because renderer should always set color
|
||||||
@@ -442,7 +650,7 @@ public class FlatTreeUI
|
|||||||
if( bg != null && !bg.equals( defaultCellNonSelectionBackground ) ) {
|
if( bg != null && !bg.equals( defaultCellNonSelectionBackground ) ) {
|
||||||
Color oldColor = g.getColor();
|
Color oldColor = g.getColor();
|
||||||
g.setColor( bg );
|
g.setColor( bg );
|
||||||
paintCellBackground( g, rendererComponent, bounds );
|
paintCellBackground( g, rendererComponent, bounds, row, false );
|
||||||
g.setColor( oldColor );
|
g.setColor( oldColor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,32 +705,73 @@ public class FlatTreeUI
|
|||||||
private void paintWideSelection( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds,
|
private void paintWideSelection( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds,
|
||||||
TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
|
TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
|
||||||
{
|
{
|
||||||
g.fillRect( 0, bounds.y, tree.getWidth(), bounds.height );
|
float arcTop, arcBottom;
|
||||||
|
arcTop = arcBottom = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
// paint expand/collapse icon
|
if( useUnitedRoundedSelection() ) {
|
||||||
// (was already painted before, but painted over with wide selection)
|
if( row > 0 && tree.isRowSelected( row - 1 ) )
|
||||||
if( shouldPaintExpandControl( path, row, isExpanded, hasBeenExpanded, isLeaf ) ) {
|
arcTop = 0;
|
||||||
paintExpandControl( g, clipBounds, insets, bounds,
|
if( row < tree.getRowCount() - 1 && tree.isRowSelected( row + 1 ) )
|
||||||
path, row, isExpanded, hasBeenExpanded, isLeaf );
|
arcBottom = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void paintCellBackground( Graphics g, Component rendererComponent, Rectangle bounds ) {
|
FlatUIUtils.paintSelection( (Graphics2D) g, 0, bounds.y, tree.getWidth(), bounds.height,
|
||||||
|
UIScale.scale( selectionInsets ), arcTop, arcTop, arcBottom, arcBottom, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void paintCellBackground( Graphics g, Component rendererComponent, Rectangle bounds,
|
||||||
|
int row, boolean paintSelection )
|
||||||
|
{
|
||||||
int xOffset = 0;
|
int xOffset = 0;
|
||||||
int imageOffset = 0;
|
int imageOffset = 0;
|
||||||
|
|
||||||
if( rendererComponent instanceof JLabel ) {
|
if( rendererComponent instanceof JLabel ) {
|
||||||
JLabel label = (JLabel) rendererComponent;
|
JLabel label = (JLabel) rendererComponent;
|
||||||
Icon icon = label.getIcon();
|
Icon icon = label.isEnabled() ? label.getIcon() : label.getDisabledIcon();
|
||||||
imageOffset = (icon != null && label.getText() != null)
|
imageOffset = (icon != null && label.getText() != null)
|
||||||
? icon.getIconWidth() + Math.max( label.getIconTextGap() - 1, 0 )
|
? icon.getIconWidth() + Math.max( label.getIconTextGap() - 1, 0 )
|
||||||
: 0;
|
: 0;
|
||||||
xOffset = label.getComponentOrientation().isLeftToRight() ? imageOffset : 0;
|
xOffset = label.getComponentOrientation().isLeftToRight() ? imageOffset : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( paintSelection ) {
|
||||||
|
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||||
|
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
|
if( useUnitedRoundedSelection() ) {
|
||||||
|
if( row > 0 && tree.isRowSelected( row - 1 ) ) {
|
||||||
|
Rectangle r = getPathBounds( tree, tree.getPathForRow( row - 1 ) );
|
||||||
|
arcTopLeft = Math.min( arcTopLeft, r.x - bounds.x );
|
||||||
|
arcTopRight = Math.min( arcTopRight, (bounds.x + bounds.width) - (r.x + r.width) );
|
||||||
|
}
|
||||||
|
if( row < tree.getRowCount() - 1 && tree.isRowSelected( row + 1 ) ) {
|
||||||
|
Rectangle r = getPathBounds( tree, tree.getPathForRow( row + 1 ) );
|
||||||
|
arcBottomLeft = Math.min( arcBottomLeft, r.x - bounds.x );
|
||||||
|
arcBottomRight = Math.min( arcBottomRight, (bounds.x + bounds.width) - (r.x + r.width) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height,
|
||||||
|
UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||||
|
} else
|
||||||
g.fillRect( bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height );
|
g.fillRect( bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean useUnitedRoundedSelection() {
|
||||||
|
return selectionArc > 0 &&
|
||||||
|
(selectionInsets == null || (selectionInsets.top == 0 && selectionInsets.bottom == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintVerticalLine( Graphics g, JComponent c, int x, int top, int bottom ) {
|
||||||
|
((Graphics2D)g).fill( new Rectangle2D.Float( x, top, UIScale.scale( 1f ), bottom - top ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintHorizontalLine( Graphics g, JComponent c, int y, int left, int right ) {
|
||||||
|
((Graphics2D)g).fill( new Rectangle2D.Float( left, y, right - left, UIScale.scale( 1f ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether dropping on a row.
|
* Checks whether dropping on a row.
|
||||||
* See DefaultTreeCellRenderer.getTreeCellRendererComponent().
|
* See DefaultTreeCellRenderer.getTreeCellRendererComponent().
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import java.awt.event.FocusEvent;
|
|||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
@@ -76,8 +77,6 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatUIUtils
|
public class FlatUIUtils
|
||||||
{
|
{
|
||||||
public static final boolean MAC_USE_QUARTZ = Boolean.getBoolean( "apple.awt.graphics.UseQuartz" );
|
|
||||||
|
|
||||||
private static boolean useSharedUIs = true;
|
private static boolean useSharedUIs = true;
|
||||||
private static final WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
private static final WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
||||||
|
|
||||||
@@ -201,6 +200,10 @@ public class FlatUIUtils
|
|||||||
return (border instanceof UIResource) ? new NonUIResourceBorder( border ) : border;
|
return (border instanceof UIResource) ? new NonUIResourceBorder( border ) : border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Border unwrapNonUIResourceBorder( Border border ) {
|
||||||
|
return (border instanceof NonUIResourceBorder) ? ((NonUIResourceBorder)border).delegate : border;
|
||||||
|
}
|
||||||
|
|
||||||
public static int minimumWidth( JComponent c, int minimumWidth ) {
|
public static int minimumWidth( JComponent c, int minimumWidth ) {
|
||||||
return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_WIDTH, minimumWidth );
|
return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_WIDTH, minimumWidth );
|
||||||
}
|
}
|
||||||
@@ -389,8 +392,7 @@ public class FlatUIUtils
|
|||||||
};
|
};
|
||||||
|
|
||||||
g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
|
g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
|
||||||
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL,
|
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE );
|
||||||
MAC_USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE );
|
|
||||||
|
|
||||||
return oldRenderingHints;
|
return oldRenderingHints;
|
||||||
}
|
}
|
||||||
@@ -443,9 +445,9 @@ public class FlatUIUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the background of a component with a round rectangle.
|
* Fills the background of a component with a rounded rectangle.
|
||||||
* <p>
|
* <p>
|
||||||
* The bounds of the painted round rectangle are
|
* The bounds of the painted rounded rectangle are
|
||||||
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
|
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
|
||||||
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
|
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
|
||||||
*
|
*
|
||||||
@@ -476,7 +478,7 @@ public class FlatUIUtils
|
|||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* <strong>Background</strong>:
|
* <strong>Background</strong>:
|
||||||
* The bounds of the filled round rectangle are
|
* The bounds of the filled rounded rectangle are
|
||||||
* {@code [x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)]}.
|
* {@code [x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)]}.
|
||||||
* The focus border and the border may paint over the background.
|
* The focus border and the border may paint over the background.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -674,6 +676,50 @@ public class FlatUIUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints a selection.
|
||||||
|
* <p>
|
||||||
|
* The bounds of the painted selection (rounded) rectangle are
|
||||||
|
* {@code x + insets.left, y + insets.top, width - insets.left - insets.right, height - insets.top - insets.bottom}.
|
||||||
|
* The given arc radius refers to the painted rectangle (and not to {@code x,y,width,height}).
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void paintSelection( Graphics2D g, int x, int y, int width, int height, Insets insets,
|
||||||
|
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight, int flags )
|
||||||
|
{
|
||||||
|
if( insets != null ) {
|
||||||
|
x += insets.left;
|
||||||
|
y += insets.top;
|
||||||
|
width -= insets.left + insets.right;
|
||||||
|
height -= insets.top + insets.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( arcTopLeft > 0 || arcTopRight > 0 || arcBottomLeft > 0 || arcBottomRight > 0 ) {
|
||||||
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
|
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||||
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||||
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
|
paintRoundedSelectionImpl( g2d, x2, y2, width2, height2,
|
||||||
|
(float) (arcTopLeft * scaleFactor), (float) (arcTopRight * scaleFactor),
|
||||||
|
(float) (arcBottomLeft * scaleFactor), (float) (arcBottomRight * scaleFactor) );
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
paintRoundedSelectionImpl( g, x, y, width, height, arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight );
|
||||||
|
|
||||||
|
} else
|
||||||
|
g.fillRect( x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void paintRoundedSelectionImpl( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
|
||||||
|
{
|
||||||
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
g.fill( FlatUIUtils.createRoundRectanglePath( x, y, width, height, arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight ) );
|
||||||
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
|
}
|
||||||
|
|
||||||
public static void paintGrip( Graphics g, int x, int y, int width, int height,
|
public static void paintGrip( Graphics g, int x, int y, int width, int height,
|
||||||
boolean horizontal, int dotCount, int dotSize, int gap, boolean centerPrecise )
|
boolean horizontal, int dotCount, int dotSize, int gap, boolean centerPrecise )
|
||||||
{
|
{
|
||||||
@@ -765,7 +811,7 @@ public class FlatUIUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
|
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius of each corner.
|
||||||
*/
|
*/
|
||||||
public static Path2D createRoundRectangle( float x, float y, float width, float height,
|
public static Path2D createRoundRectangle( float x, float y, float width, float height,
|
||||||
float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
|
float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
|
||||||
@@ -804,7 +850,7 @@ public class FlatUIUtils
|
|||||||
double ciBottomLeft = arcBottomLeft * ci;
|
double ciBottomLeft = arcBottomLeft * ci;
|
||||||
double ciBottomRight = arcBottomRight * ci;
|
double ciBottomRight = arcBottomRight * ci;
|
||||||
|
|
||||||
Path2D rect = new Path2D.Float();
|
Path2D rect = new Path2D.Float( Path2D.WIND_NON_ZERO, 16 );
|
||||||
rect.moveTo( x2 - arcTopRight, y );
|
rect.moveTo( x2 - arcTopRight, y );
|
||||||
rect.curveTo( x2 - ciTopRight, y,
|
rect.curveTo( x2 - ciTopRight, y,
|
||||||
x2, y + ciTopRight,
|
x2, y + ciTopRight,
|
||||||
@@ -826,6 +872,27 @@ public class FlatUIUtils
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a rounded triangle shape for the given points and arc radius.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static Shape createRoundTrianglePath( float x1, float y1, float x2, float y2,
|
||||||
|
float x3, float y3, float arc )
|
||||||
|
{
|
||||||
|
double averageSideLength = (distance( x1,y1, x2,y2 ) + distance( x2,y2, x3,y3 ) + distance( x3,y3, x1,y1 )) / 3;
|
||||||
|
double t1 = (1 / averageSideLength) * arc;
|
||||||
|
double t2 = 1 - t1;
|
||||||
|
|
||||||
|
return createPath(
|
||||||
|
lerp( x3, x1, t2 ), lerp( y3, y1, t2 ),
|
||||||
|
QUAD_TO, x1, y1, lerp( x1, x2, t1 ), lerp( y1, y2, t1 ),
|
||||||
|
lerp( x1, x2, t2 ), lerp( y1, y2, t2 ),
|
||||||
|
QUAD_TO, x2, y2, lerp( x2, x3, t1 ), lerp( y2, y3, t1 ),
|
||||||
|
lerp( x2, x3, t2 ), lerp( y2, y3, t2 ),
|
||||||
|
QUAD_TO, x3, y3, lerp( x3, x1, t1 ), lerp( y3, y1, t1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints a chevron or triangle arrow in the center of the given rectangle.
|
* Paints a chevron or triangle arrow in the center of the given rectangle.
|
||||||
*
|
*
|
||||||
@@ -838,13 +905,15 @@ public class FlatUIUtils
|
|||||||
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
|
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
|
||||||
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
|
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
|
||||||
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
|
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
|
||||||
|
* @param arrowThickness the thickness of the painted chevron arrow (will be scaled)
|
||||||
* @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
* @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||||
* @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
* @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||||
*
|
*
|
||||||
* @since 1.1
|
* @since 3
|
||||||
*/
|
*/
|
||||||
public static void paintArrow( Graphics2D g, int x, int y, int width, int height,
|
public static void paintArrow( Graphics2D g, int x, int y, int width, int height,
|
||||||
int direction, boolean chevron, int arrowSize, float xOffset, float yOffset )
|
int direction, boolean chevron, int arrowSize, float arrowThickness,
|
||||||
|
float xOffset, float yOffset )
|
||||||
{
|
{
|
||||||
// compute arrow width/height
|
// compute arrow width/height
|
||||||
// - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5)
|
// - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5)
|
||||||
@@ -878,7 +947,7 @@ debug*/
|
|||||||
Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
|
Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
Stroke oldStroke = g.getStroke();
|
Stroke oldStroke = g.getStroke();
|
||||||
g.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
g.setStroke( new BasicStroke( UIScale.scale( arrowThickness ) ) );
|
||||||
drawShapePure( g, arrowShape );
|
drawShapePure( g, arrowShape );
|
||||||
g.setStroke( oldStroke );
|
g.setStroke( oldStroke );
|
||||||
} else {
|
} else {
|
||||||
@@ -935,6 +1004,12 @@ debug*/
|
|||||||
}
|
}
|
||||||
debug*/
|
debug*/
|
||||||
|
|
||||||
|
/** @since 3 */ public static final double MOVE_TO = -1_000_000_000_001.;
|
||||||
|
/** @since 3 */ public static final double QUAD_TO = -1_000_000_000_002.;
|
||||||
|
/** @since 3 */ public static final double CURVE_TO = -1_000_000_000_003.;
|
||||||
|
/** @since 3 */ public static final double ROUNDED = -1_000_000_000_004.;
|
||||||
|
/** @since 3 */ public static final double CLOSE_PATH = -1_000_000_000_005.;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a closed path for the given points.
|
* Creates a closed path for the given points.
|
||||||
*/
|
*/
|
||||||
@@ -946,15 +1021,88 @@ debug*/
|
|||||||
* Creates an open or closed path for the given points.
|
* Creates an open or closed path for the given points.
|
||||||
*/
|
*/
|
||||||
public static Path2D createPath( boolean close, double... points ) {
|
public static Path2D createPath( boolean close, double... points ) {
|
||||||
Path2D path = new Path2D.Float();
|
Path2D path = new Path2D.Float( Path2D.WIND_NON_ZERO, points.length / 2 + (close ? 1 : 0) );
|
||||||
path.moveTo( points[0], points[1] );
|
path.moveTo( points[0], points[1] );
|
||||||
for( int i = 2; i < points.length; i += 2 )
|
for( int i = 2; i < points.length; ) {
|
||||||
path.lineTo( points[i], points[i + 1] );
|
double p = points[i];
|
||||||
|
if( p == MOVE_TO ) {
|
||||||
|
// move pointer to
|
||||||
|
// params: x, y
|
||||||
|
path.moveTo( points[i + 1], points[i + 2] );
|
||||||
|
i += 3;
|
||||||
|
} else if( p == QUAD_TO ) {
|
||||||
|
// add quadratic curve
|
||||||
|
// params: x1, y1, x2, y2
|
||||||
|
path.quadTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4] );
|
||||||
|
i += 5;
|
||||||
|
} else if( p == CURVE_TO ) {
|
||||||
|
// add bezier curve
|
||||||
|
// params: x1, y1, x2, y2, x3, y3
|
||||||
|
path.curveTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4], points[i + 5], points[i + 6] );
|
||||||
|
i += 7;
|
||||||
|
} else if( p == ROUNDED ) {
|
||||||
|
// add rounded corner
|
||||||
|
// params: x, y, arc
|
||||||
|
double x = points[i + 1];
|
||||||
|
double y = points[i + 2];
|
||||||
|
double arc = points[i + 3];
|
||||||
|
|
||||||
|
// index of next point
|
||||||
|
int ip2 = i + 4;
|
||||||
|
if( points[ip2] == QUAD_TO || points[ip2] == ROUNDED )
|
||||||
|
ip2++;
|
||||||
|
|
||||||
|
// previous and next points
|
||||||
|
Point2D p1 = path.getCurrentPoint();
|
||||||
|
double x1 = p1.getX();
|
||||||
|
double y1 = p1.getY();
|
||||||
|
double x2 = points[ip2];
|
||||||
|
double y2 = points[ip2 + 1];
|
||||||
|
|
||||||
|
double d1 = distance( x, y, x1, y1 );
|
||||||
|
double d2 = distance( x, y, x2, y2 );
|
||||||
|
double t1 = 1 - ((1 / d1) * arc);
|
||||||
|
double t2 = (1 / d2) * arc;
|
||||||
|
|
||||||
|
path.lineTo( lerp( x1, x, t1 ), lerp( y1, y, t1 ) );
|
||||||
|
path.quadTo( x, y, lerp( x, x2, t2 ), lerp( y, y2, t2 ) );
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
} else if( p == CLOSE_PATH ) {
|
||||||
|
// close path
|
||||||
|
// params: -
|
||||||
|
path.closePath();
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
// add line to
|
||||||
|
// params: x, y
|
||||||
|
path.lineTo( p, points[i + 1] );
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
if( close )
|
if( close )
|
||||||
path.closePath();
|
path.closePath();
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates linear interpolation between two values.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support
|
||||||
|
*/
|
||||||
|
private static double lerp( double v1, double v2, double t ) {
|
||||||
|
return (v1 * (1 - t)) + (v2 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the distance between two points.
|
||||||
|
*/
|
||||||
|
private static double distance( double x1, double y1, double x2, double y2 ) {
|
||||||
|
double dx = x2 - x1;
|
||||||
|
double dy = y2 - y1;
|
||||||
|
return Math.sqrt( (dx * dx) + (dy * dy) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given shape with disabled stroke normalization.
|
* Draws the given shape with disabled stroke normalization.
|
||||||
* The x/y coordinates of the shape are translated by a half pixel.
|
* The x/y coordinates of the shape are translated by a half pixel.
|
||||||
|
|||||||
@@ -606,9 +606,10 @@ debug*/
|
|||||||
if( resizeDir == S_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
|
if( resizeDir == S_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
|
||||||
newBounds.height = (yOnScreen + dragBottomOffset) - newBounds.y;
|
newBounds.height = (yOnScreen + dragBottomOffset) - newBounds.y;
|
||||||
if( limitToParentBounds() ) {
|
if( limitToParentBounds() ) {
|
||||||
int parentHeight = getParentBounds().height;
|
Rectangle parentBounds = getParentBounds();
|
||||||
if( newBounds.y + newBounds.height > parentHeight )
|
int parentBottomY = parentBounds.y + parentBounds.height;
|
||||||
newBounds.height = parentHeight - newBounds.y;
|
if( newBounds.y + newBounds.height > parentBottomY )
|
||||||
|
newBounds.height = parentBottomY - newBounds.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,9 +625,10 @@ debug*/
|
|||||||
if( resizeDir == E_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
|
if( resizeDir == E_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
|
||||||
newBounds.width = (xOnScreen + dragRightOffset) - newBounds.x;
|
newBounds.width = (xOnScreen + dragRightOffset) - newBounds.x;
|
||||||
if( limitToParentBounds() ) {
|
if( limitToParentBounds() ) {
|
||||||
int parentWidth = getParentBounds().width;
|
Rectangle parentBounds = getParentBounds();
|
||||||
if( newBounds.x + newBounds.width > parentWidth )
|
int parentRightX = parentBounds.x + parentBounds.width;
|
||||||
newBounds.width = parentWidth - newBounds.x;
|
if( newBounds.x + newBounds.width > parentRightX )
|
||||||
|
newBounds.width = parentRightX - newBounds.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,19 @@ public class ColorFunctions
|
|||||||
return HSLColor.toRGB( hsl[0], hsl[1], hsl[2], alpha );
|
return HSLColor.toRGB( hsl[0], hsl[1], hsl[2], alpha );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the opacity (alpha) of a color.
|
||||||
|
*
|
||||||
|
* @param color base color
|
||||||
|
* @param amount the amount (in range 0-1) of the new opacity
|
||||||
|
* @return new color
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static Color fade( Color color, float amount ) {
|
||||||
|
int newAlpha = Math.round( 255 * amount );
|
||||||
|
return new Color( (color.getRGB() & 0xffffff) | (newAlpha << 24), true );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a color that is a mixture of two colors.
|
* Returns a color that is a mixture of two colors.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.util;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontFormatException;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.swing.plaf.UIResource;
|
||||||
|
import javax.swing.text.StyleContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for fonts.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FontUtils
|
||||||
|
{
|
||||||
|
private static Map<String, Runnable> loadersMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a composite font for the given family, style and size.
|
||||||
|
* A composite font that is able to display all Unicode characters.
|
||||||
|
* The font family is loaded if necessary via {@link #loadFontFamily(String)}.
|
||||||
|
* <p>
|
||||||
|
* To get fonts derived from returned fonts, it is recommended to use one of the
|
||||||
|
* {@link Font#deriveFont} methods instead of invoking this method.
|
||||||
|
*/
|
||||||
|
public static Font getCompositeFont( String family, int style, int size ) {
|
||||||
|
loadFontFamily( family );
|
||||||
|
|
||||||
|
// using StyleContext.getFont() here because it uses
|
||||||
|
// sun.font.FontUtilities.getCompositeFontUIResource()
|
||||||
|
// and creates a composite font that is able to display all Unicode characters
|
||||||
|
Font font = StyleContext.getDefaultStyleContext().getFont( family, style, size );
|
||||||
|
|
||||||
|
// always return non-UIResource font to avoid side effects when using font
|
||||||
|
// because Swing uninstalls UIResource fonts when switching L&F
|
||||||
|
// (StyleContext.getFont() may return a UIResource)
|
||||||
|
if( font instanceof UIResource )
|
||||||
|
font = font.deriveFont( font.getStyle() );
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a font family for lazy loading via {@link #loadFontFamily(String)}.
|
||||||
|
* <p>
|
||||||
|
* The given runnable is invoked when the given font family should be loaded.
|
||||||
|
* The runnable should invoke {@link #installFont(URL)} to load and register font(s)
|
||||||
|
* for the family.
|
||||||
|
* A family may consist of up to four font files for the supported font styles:
|
||||||
|
* regular (plain), italic, bold and bold-italic.
|
||||||
|
*/
|
||||||
|
public static void registerFontFamilyLoader( String family, Runnable loader ) {
|
||||||
|
if( loadersMap == null )
|
||||||
|
loadersMap = new HashMap<>();
|
||||||
|
loadersMap.put( family, loader );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a font family previously registered via {@link #registerFontFamilyLoader(String, Runnable)}.
|
||||||
|
* If the family is already loaded or no londer is registered for that family, nothing happens.
|
||||||
|
*/
|
||||||
|
public static void loadFontFamily( String family ) {
|
||||||
|
if( !hasLoaders() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Runnable loader = loadersMap.remove( family );
|
||||||
|
if( loader != null )
|
||||||
|
loader.run();
|
||||||
|
|
||||||
|
if( loadersMap.isEmpty() )
|
||||||
|
loadersMap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a font file from the given url and registers it in the graphics environment.
|
||||||
|
* Uses {@link Font#createFont(int, InputStream)} and {@link GraphicsEnvironment#registerFont(Font)}.
|
||||||
|
*/
|
||||||
|
public static boolean installFont( URL url ) {
|
||||||
|
try( InputStream in = url.openStream() ) {
|
||||||
|
Font font = Font.createFont( Font.TRUETYPE_FONT, in );
|
||||||
|
return GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
|
||||||
|
} catch( FontFormatException | IOException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to install font " + url, ex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all font familiy names available in the graphics environment.
|
||||||
|
* This invokes {@link GraphicsEnvironment#getAvailableFontFamilyNames()} and
|
||||||
|
* appends families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
|
||||||
|
* to the result.
|
||||||
|
*/
|
||||||
|
public static String[] getAvailableFontFamilyNames() {
|
||||||
|
String[] availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
|
||||||
|
if( !hasLoaders() )
|
||||||
|
return availableFontFamilyNames;
|
||||||
|
|
||||||
|
// append families that are not yet loaded
|
||||||
|
ArrayList<String> result = new ArrayList<>( availableFontFamilyNames.length + loadersMap.size() );
|
||||||
|
for( String name : availableFontFamilyNames )
|
||||||
|
result.add( name );
|
||||||
|
for( String name : loadersMap.keySet() ) {
|
||||||
|
if( !result.contains( name ) )
|
||||||
|
result.add( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toArray( new String[result.size()] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all fonts available in the graphics environment.
|
||||||
|
* This first loads all families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
|
||||||
|
* and then invokes {@link GraphicsEnvironment#getAllFonts()}.
|
||||||
|
*/
|
||||||
|
public static Font[] getAllFonts() {
|
||||||
|
if( hasLoaders() ) {
|
||||||
|
// load all registered families
|
||||||
|
String[] families = loadersMap.keySet().toArray( new String[loadersMap.size()] );
|
||||||
|
for( String family : families )
|
||||||
|
loadFontFamily( family );
|
||||||
|
}
|
||||||
|
|
||||||
|
return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasLoaders() {
|
||||||
|
return loadersMap != null && !loadersMap.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.util;
|
package com.formdev.flatlaf.util;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.font.GlyphVector;
|
import java.awt.font.GlyphVector;
|
||||||
@@ -51,40 +52,47 @@ public class HiDPIUtils
|
|||||||
AffineTransform t = g.getTransform();
|
AffineTransform t = g.getTransform();
|
||||||
|
|
||||||
// get scale X/Y and shear X/Y
|
// get scale X/Y and shear X/Y
|
||||||
double scaleX = t.getScaleX();
|
final double scaleX = t.getScaleX();
|
||||||
double scaleY = t.getScaleY();
|
final double scaleY = t.getScaleY();
|
||||||
double shearX = t.getShearX();
|
final double shearX = t.getShearX();
|
||||||
double shearY = t.getShearY();
|
final double shearY = t.getShearY();
|
||||||
|
|
||||||
// check whether rotated
|
// check whether rotated
|
||||||
// (also check for negative scale X/Y because shear X/Y are zero for 180 degrees rotation)
|
// (also check for negative scale X/Y because shear X/Y are zero for 180 degrees rotation)
|
||||||
boolean rotated = (shearX != 0 || shearY != 0 || scaleX <= 0 || scaleY <= 0);
|
boolean rotated = (shearX != 0 || shearY != 0 || scaleX <= 0 || scaleY <= 0);
|
||||||
|
|
||||||
|
// calculate non rotated scale factors
|
||||||
|
final double realScaleX, realScaleY;
|
||||||
if( rotated ) {
|
if( rotated ) {
|
||||||
// resulting scale X/Y values are always positive
|
// resulting scale X/Y values are always positive
|
||||||
scaleX = Math.hypot( scaleX, shearX );
|
realScaleX = Math.hypot( scaleX, shearX );
|
||||||
scaleY = Math.hypot( scaleY, shearY );
|
realScaleY = Math.hypot( scaleY, shearY );
|
||||||
} else {
|
} else {
|
||||||
// make scale X/Y positive
|
// make scale X/Y positive
|
||||||
scaleX = Math.abs( scaleX );
|
realScaleX = Math.abs( scaleX );
|
||||||
scaleY = Math.abs( scaleY );
|
realScaleY = Math.abs( scaleY );
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether scaled
|
// check whether scaled
|
||||||
if( scaleX == 1 && scaleY == 1 ) {
|
if( realScaleX == 1 && realScaleY == 1 ) {
|
||||||
painter.paint( g, x, y, width, height, 1 );
|
painter.paint( g, x, y, width, height, 1 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate x and y (this is equal to t.translate( x, y ))
|
||||||
|
double px = (x * scaleX) + (y * shearX) + t.getTranslateX();
|
||||||
|
double py = (y * scaleY) + (x * shearY) + t.getTranslateY();
|
||||||
|
|
||||||
// scale rectangle
|
// scale rectangle
|
||||||
Rectangle2D.Double scaledRect = scale( scaleX, scaleY, t, x, y, width, height );
|
Rectangle2D.Double scaledRect = scale( realScaleX, realScaleY, px, py, width, height );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// unscale to factor 1.0, keep rotation and move origin (to whole numbers)
|
// unscale to factor 1.0, keep rotation and move origin (to whole numbers)
|
||||||
AffineTransform t1x;
|
AffineTransform t1x;
|
||||||
if( rotated ) {
|
if( rotated ) {
|
||||||
t1x = new AffineTransform( t.getScaleX(), t.getShearY(), t.getShearX(), t.getScaleY(),
|
t1x = new AffineTransform( scaleX, shearY, shearX, scaleY,
|
||||||
Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) );
|
Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) );
|
||||||
t1x.scale( 1. / scaleX, 1. / scaleY );
|
t1x.scale( 1. / realScaleX, 1. / realScaleY );
|
||||||
} else
|
} else
|
||||||
t1x = new AffineTransform( 1, 0, 0, 1, Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) );
|
t1x = new AffineTransform( 1, 0, 0, 1, Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) );
|
||||||
g.setTransform( t1x );
|
g.setTransform( t1x );
|
||||||
@@ -93,7 +101,7 @@ public class HiDPIUtils
|
|||||||
int sheight = (int) scaledRect.height;
|
int sheight = (int) scaledRect.height;
|
||||||
|
|
||||||
// paint
|
// paint
|
||||||
painter.paint( g, 0, 0, swidth, sheight, scaleX );
|
painter.paint( g, 0, 0, swidth, sheight, realScaleX );
|
||||||
} finally {
|
} finally {
|
||||||
// restore original transform
|
// restore original transform
|
||||||
g.setTransform( t );
|
g.setTransform( t );
|
||||||
@@ -105,10 +113,7 @@ public class HiDPIUtils
|
|||||||
* sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(),
|
* sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(),
|
||||||
* which is used by Graphics.fillRect().
|
* which is used by Graphics.fillRect().
|
||||||
*/
|
*/
|
||||||
private static Rectangle2D.Double scale( double scaleX, double scaleY, AffineTransform t, int x, int y, int width, int height ) {
|
private static Rectangle2D.Double scale( double scaleX, double scaleY, double px, double py, int width, int height ) {
|
||||||
double px = (x * scaleX) + t.getTranslateX();
|
|
||||||
double py = (y * scaleY) + t.getTranslateY();
|
|
||||||
|
|
||||||
double newX = normalize( px );
|
double newX = normalize( px );
|
||||||
double newY = normalize( py );
|
double newY = normalize( py );
|
||||||
double newWidth = normalize( px + (width * scaleX) ) - newX;
|
double newWidth = normalize( px + (width * scaleX) ) - newX;
|
||||||
@@ -141,13 +146,26 @@ public class HiDPIUtils
|
|||||||
if( !useTextYCorrection() || !SystemInfo.isWindows )
|
if( !useTextYCorrection() || !SystemInfo.isWindows )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if( !SystemInfo.isJava_9_orLater )
|
if( !SystemInfo.isJava_9_orLater ) {
|
||||||
return UIScale.getUserScaleFactor() > 1 ? -UIScale.scale( 0.625f ) : 0;
|
// Java 8
|
||||||
|
float scaleFactor = getUserScaleFactor();
|
||||||
|
if( scaleFactor > 1 ) {
|
||||||
|
switch( g.getFont().getFamily() ) {
|
||||||
|
case "Segoe UI":
|
||||||
|
case "Segoe UI Light":
|
||||||
|
case "Segoe UI Semibold":
|
||||||
|
return -((scaleFactor == 2.25f || scaleFactor == 4f ? 0.875f : 0.625f) * scaleFactor);
|
||||||
|
|
||||||
AffineTransform t = g.getTransform();
|
case "Noto Sans":
|
||||||
double scaleY = t.getScaleY();
|
case "Open Sans":
|
||||||
if( scaleY < 1.25 )
|
return -(0.3f * scaleFactor);
|
||||||
return 0;
|
|
||||||
|
case "Verdana":
|
||||||
|
return -((scaleFactor < 2 ? 0.4f : 0.3f) * scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Java 9 and later
|
||||||
|
|
||||||
// Text is painted at slightly different Y positions depending on scale factor
|
// Text is painted at slightly different Y positions depending on scale factor
|
||||||
// and Y position of component.
|
// and Y position of component.
|
||||||
@@ -158,20 +176,73 @@ public class HiDPIUtils
|
|||||||
// - Java adds 0.5 to X/Y positions before drawing string in BufferedTextPipe.enqueueGlyphList()
|
// - Java adds 0.5 to X/Y positions before drawing string in BufferedTextPipe.enqueueGlyphList()
|
||||||
|
|
||||||
// this is not the optimal solution, but works very good in most cases
|
// this is not the optimal solution, but works very good in most cases
|
||||||
// (tested with class FlatPaintingStringTest on Windows 10 with font "Segoe UI")
|
// (tested with class FlatPaintingStringTest on Windows 11)
|
||||||
if( scaleY <= 1.25 )
|
|
||||||
return -0.875f;
|
switch( g.getFont().getFamily() ) {
|
||||||
if( scaleY <= 1.5 )
|
case "Segoe UI":
|
||||||
return -0.625f;
|
case "Segoe UI Light":
|
||||||
if( scaleY <= 1.75 )
|
case "Segoe UI Semibold":
|
||||||
return -0.875f;
|
case "Verdana":
|
||||||
if( scaleY <= 2.0 )
|
case Font.DIALOG:
|
||||||
return -0.75f;
|
case Font.SANS_SERIF:
|
||||||
if( scaleY <= 2.25 )
|
return correctionForScaleY( g, CORRECTION_SEGOE_UI );
|
||||||
return -0.875f;
|
|
||||||
if( scaleY <= 3.5 )
|
case "Tahoma":
|
||||||
return -0.75f;
|
return correctionForScaleY( g, CORRECTION_TAHOMA );
|
||||||
return -0.875f;
|
|
||||||
|
case "Inter":
|
||||||
|
case "Inter Light":
|
||||||
|
case "Inter Semi Bold":
|
||||||
|
case "Roboto":
|
||||||
|
case "Roboto Light":
|
||||||
|
case "Roboto Medium":
|
||||||
|
return correctionForScaleY( g, CORRECTION_INTER );
|
||||||
|
|
||||||
|
case "Noto Sans":
|
||||||
|
case "Open Sans":
|
||||||
|
return correctionForScaleY( g, CORRECTION_OPEN_SANS );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final float[]
|
||||||
|
SCALE_FACTORS = { 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 3f, 3.5f, 4f },
|
||||||
|
|
||||||
|
CORRECTION_SEGOE_UI = { -0.5f, -0.5f, -0.625f, -0.75f, -0.75f, -0.75f, -0.75f, -0.75f, -0.875f },
|
||||||
|
CORRECTION_TAHOMA = { -0.25f, -0.25f, -0.25f, -0f, -0.125f, -0.125f, -0.125f, -0.125f, -0f },
|
||||||
|
CORRECTION_INTER = { -0.25f, -0.25f, -0.25f, -0f, -0.125f, -0.125f, -0f, -0.25f, -0f },
|
||||||
|
CORRECTION_OPEN_SANS = { -0.5f, -0.25f, -0.25f, -0f, -0.25f, -0.25f, -0f, -0.25f, -0.25f };
|
||||||
|
|
||||||
|
private static float correctionForScaleY( Graphics2D g, float[] correction ) {
|
||||||
|
if( correction.length != 9 )
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
double scaleY = g.getTransform().getScaleY();
|
||||||
|
return (scaleY < 1.25) ? 0 : correction[scaleFactor2index( (float) scaleY )];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int scaleFactor2index( float scaleFactor ) {
|
||||||
|
for( int i = 0; i < SCALE_FACTORS.length; i++ ) {
|
||||||
|
if( scaleFactor <= SCALE_FACTORS[i] )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return SCALE_FACTORS.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Boolean useDebugScaleFactor;
|
||||||
|
|
||||||
|
private static boolean useDebugScaleFactor() {
|
||||||
|
if( useDebugScaleFactor == null )
|
||||||
|
useDebugScaleFactor = FlatSystemProperties.getBoolean( "FlatLaf.debug.HiDPIUtils.useDebugScaleFactor", false );
|
||||||
|
return useDebugScaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getUserScaleFactor() {
|
||||||
|
return !useDebugScaleFactor()
|
||||||
|
? UIScale.getUserScaleFactor()
|
||||||
|
: Float.parseFloat( System.getProperty( "FlatLaf.debug.HiDPIUtils.debugScaleFactor", "1" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -100,8 +100,13 @@ debug*/
|
|||||||
Image image = getResolutionVariant( destImageWidth, destImageHeight );
|
Image image = getResolutionVariant( destImageWidth, destImageHeight );
|
||||||
|
|
||||||
// size of image
|
// size of image
|
||||||
int imageWidth = image.getWidth( null );
|
int imageWidth = -1;
|
||||||
int imageHeight = image.getHeight( null );
|
int imageHeight = -1;
|
||||||
|
|
||||||
|
if (image != null) {
|
||||||
|
imageWidth = image.getWidth( null );
|
||||||
|
imageHeight = image.getHeight( null );
|
||||||
|
}
|
||||||
|
|
||||||
// paint red rectangle if image has invalid size (e.g. not found)
|
// paint red rectangle if image has invalid size (e.g. not found)
|
||||||
if( imageWidth < 0 || imageHeight < 0 ) {
|
if( imageWidth < 0 || imageHeight < 0 ) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.util;
|
|||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import com.formdev.flatlaf.ui.FlatNativeWindowsLibrary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides information about the current system.
|
* Provides information about the current system.
|
||||||
@@ -34,9 +35,7 @@ public class SystemInfo
|
|||||||
// OS versions
|
// OS versions
|
||||||
public static final long osVersion;
|
public static final long osVersion;
|
||||||
public static final boolean isWindows_10_orLater;
|
public static final boolean isWindows_10_orLater;
|
||||||
/** <strong>Note</strong>: This requires Java 8u321, 11.0.14, 17.0.2 or 18 (or later).
|
/** @since 2 */ public static final boolean isWindows_11_orLater;
|
||||||
* (see https://bugs.openjdk.java.net/browse/JDK-8274840)
|
|
||||||
* @since 2 */ public static final boolean isWindows_11_orLater;
|
|
||||||
public static final boolean isMacOS_10_11_ElCapitan_orLater;
|
public static final boolean isMacOS_10_11_ElCapitan_orLater;
|
||||||
public static final boolean isMacOS_10_14_Mojave_orLater;
|
public static final boolean isMacOS_10_14_Mojave_orLater;
|
||||||
public static final boolean isMacOS_10_15_Catalina_orLater;
|
public static final boolean isMacOS_10_15_Catalina_orLater;
|
||||||
@@ -80,8 +79,6 @@ public class SystemInfo
|
|||||||
// OS versions
|
// OS versions
|
||||||
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
||||||
isWindows_10_orLater = (isWindows && osVersion >= toVersion( 10, 0, 0, 0 ));
|
isWindows_10_orLater = (isWindows && osVersion >= toVersion( 10, 0, 0, 0 ));
|
||||||
isWindows_11_orLater = (isWindows_10_orLater && osName.length() > "windows ".length() &&
|
|
||||||
scanVersion( osName.substring( "windows ".length() ) ) >= toVersion( 11, 0, 0, 0 ));
|
|
||||||
isMacOS_10_11_ElCapitan_orLater = (isMacOS && osVersion >= toVersion( 10, 11, 0, 0 ));
|
isMacOS_10_11_ElCapitan_orLater = (isMacOS && osVersion >= toVersion( 10, 11, 0, 0 ));
|
||||||
isMacOS_10_14_Mojave_orLater = (isMacOS && osVersion >= toVersion( 10, 14, 0, 0 ));
|
isMacOS_10_14_Mojave_orLater = (isMacOS && osVersion >= toVersion( 10, 14, 0, 0 ));
|
||||||
isMacOS_10_15_Catalina_orLater = (isMacOS && osVersion >= toVersion( 10, 15, 0, 0 ));
|
isMacOS_10_15_Catalina_orLater = (isMacOS && osVersion >= toVersion( 10, 15, 0, 0 ));
|
||||||
@@ -116,9 +113,27 @@ public class SystemInfo
|
|||||||
|
|
||||||
// features
|
// features
|
||||||
// available since Java 12; backported to Java 11.0.8 and 8u292
|
// available since Java 12; backported to Java 11.0.8 and 8u292
|
||||||
isMacFullWindowContentSupported =
|
isMacFullWindowContentSupported = isMacOS &&
|
||||||
javaVersion >= toVersion( 11, 0, 8, 0 ) ||
|
(javaVersion >= toVersion( 11, 0, 8, 0 ) ||
|
||||||
(javaVersion >= toVersion( 1, 8, 0, 292 ) && !isJava_9_orLater);
|
(javaVersion >= toVersion( 1, 8, 0, 292 ) && !isJava_9_orLater));
|
||||||
|
|
||||||
|
|
||||||
|
// Note: Keep following at the end of this block because (optional) loading
|
||||||
|
// of native library uses fields of this class. E.g. isX86_64
|
||||||
|
|
||||||
|
// Windows 11 detection is implemented in Java 8u321, 11.0.14, 17.0.2 and 18 (or later).
|
||||||
|
// (see https://bugs.openjdk.java.net/browse/JDK-8274840)
|
||||||
|
// For older Java versions, use native library to get OS build number.
|
||||||
|
boolean isWin_11_orLater = false;
|
||||||
|
try {
|
||||||
|
isWin_11_orLater = isWindows_10_orLater &&
|
||||||
|
(scanVersion( StringUtils.removeLeading( osName, "windows " ) ) >= toVersion( 11, 0, 0, 0 ) ||
|
||||||
|
(FlatNativeWindowsLibrary.isLoaded() && FlatNativeWindowsLibrary.getOSBuildNumber() >= 22000));
|
||||||
|
} catch( Throwable ex ) {
|
||||||
|
// catch to avoid that application can not start if native library is not up-to-date
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
isWindows_11_orLater = isWin_11_orLater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long scanVersion( String version ) {
|
public static long scanVersion( String version ) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ module com.formdev.flatlaf {
|
|||||||
|
|
||||||
exports com.formdev.flatlaf;
|
exports com.formdev.flatlaf;
|
||||||
exports com.formdev.flatlaf.icons;
|
exports com.formdev.flatlaf.icons;
|
||||||
|
exports com.formdev.flatlaf.themes;
|
||||||
exports com.formdev.flatlaf.ui;
|
exports com.formdev.flatlaf.ui;
|
||||||
exports com.formdev.flatlaf.util;
|
exports com.formdev.flatlaf.util;
|
||||||
|
|
||||||
|
|||||||
@@ -50,19 +50,20 @@
|
|||||||
@selectionInactiveForeground = @foreground
|
@selectionInactiveForeground = @foreground
|
||||||
|
|
||||||
# menu
|
# menu
|
||||||
|
@menuSelectionBackground = @selectionBackground
|
||||||
@menuHoverBackground = lighten(@menuBackground,10%,derived)
|
@menuHoverBackground = lighten(@menuBackground,10%,derived)
|
||||||
@menuCheckBackground = darken(@selectionBackground,10%,derived noAutoInverse)
|
@menuCheckBackground = darken(@menuSelectionBackground,10%,derived noAutoInverse)
|
||||||
@menuAcceleratorForeground = darken(@foreground,15%)
|
@menuAcceleratorForeground = darken(@foreground,15%)
|
||||||
@menuAcceleratorSelectionForeground = @selectionForeground
|
@menuAcceleratorSelectionForeground = @selectionForeground
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
@cellFocusColor = #000
|
@cellFocusColor = lighten(@selectionBackground,10%)
|
||||||
@icon = shade(@foreground,7%)
|
@icon = shade(@foreground,7%)
|
||||||
|
|
||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
# set @accentColor to use single accent color or
|
# set @accentColor to use single accent color or
|
||||||
# modify @accentBaseColor to use variations of accent base color
|
# modify @accentBaseColor to use variations of accent base color
|
||||||
@accentColor = null
|
@accentColor = systemColor(accent,null)
|
||||||
@accentBaseColor = #4B6EAF
|
@accentBaseColor = #4B6EAF
|
||||||
@accentBase2Color = lighten(saturate(spin(@accentBaseColor,-8),13%),5%)
|
@accentBase2Color = lighten(saturate(spin(@accentBaseColor,-8),13%),5%)
|
||||||
# accent color variations
|
# accent color variations
|
||||||
@@ -330,6 +331,8 @@ Table.gridColor = lighten($Table.background,8%)
|
|||||||
|
|
||||||
#---- TableHeader ----
|
#---- TableHeader ----
|
||||||
|
|
||||||
|
TableHeader.hoverBackground = lighten($TableHeader.background,5%,derived)
|
||||||
|
TableHeader.pressedBackground = lighten($TableHeader.background,10%,derived)
|
||||||
TableHeader.separatorColor = lighten($TableHeader.background,10%)
|
TableHeader.separatorColor = lighten($TableHeader.background,10%)
|
||||||
TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||||
|
|
||||||
@@ -349,6 +352,11 @@ ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,3%,de
|
|||||||
ToggleButton.toolbar.selectedBackground = lighten($ToggleButton.background,7%,derived)
|
ToggleButton.toolbar.selectedBackground = lighten($ToggleButton.background,7%,derived)
|
||||||
|
|
||||||
|
|
||||||
|
#---- ToolBar ----
|
||||||
|
|
||||||
|
ToolBar.hoverButtonGroupBackground = lighten($ToolBar.background,3%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToolTip ----
|
#---- ToolTip ----
|
||||||
|
|
||||||
ToolTip.border = 4,6,4,6
|
ToolTip.border = 4,6,4,6
|
||||||
|
|||||||
@@ -285,6 +285,11 @@ ComboBox.buttonDisabledArrowColor = @buttonDisabledArrowColor
|
|||||||
ComboBox.buttonHoverArrowColor = @buttonHoverArrowColor
|
ComboBox.buttonHoverArrowColor = @buttonHoverArrowColor
|
||||||
ComboBox.buttonPressedArrowColor = @buttonPressedArrowColor
|
ComboBox.buttonPressedArrowColor = @buttonPressedArrowColor
|
||||||
|
|
||||||
|
ComboBox.popupInsets = 0,0,0,0
|
||||||
|
ComboBox.selectionInsets = 0,0,0,0
|
||||||
|
ComboBox.selectionArc = 0
|
||||||
|
ComboBox.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
#---- Component ----
|
||||||
|
|
||||||
@@ -390,6 +395,8 @@ InternalFrameTitlePane.border = 0,8,0,0
|
|||||||
|
|
||||||
List.border = 0,0,0,0
|
List.border = 0,0,0,0
|
||||||
List.cellMargins = 1,6,1,6
|
List.cellMargins = 1,6,1,6
|
||||||
|
List.selectionInsets = 0,0,0,0
|
||||||
|
List.selectionArc = 0
|
||||||
List.cellFocusColor = @cellFocusColor
|
List.cellFocusColor = @cellFocusColor
|
||||||
List.cellNoFocusBorder = com.formdev.flatlaf.ui.FlatListCellBorder$Default
|
List.cellNoFocusBorder = com.formdev.flatlaf.ui.FlatListCellBorder$Default
|
||||||
List.focusCellHighlightBorder = com.formdev.flatlaf.ui.FlatListCellBorder$Focused
|
List.focusCellHighlightBorder = com.formdev.flatlaf.ui.FlatListCellBorder$Focused
|
||||||
@@ -422,6 +429,9 @@ MenuBar.border = com.formdev.flatlaf.ui.FlatMenuBarBorder
|
|||||||
MenuBar.background = @menuBackground
|
MenuBar.background = @menuBackground
|
||||||
MenuBar.hoverBackground = @menuHoverBackground
|
MenuBar.hoverBackground = @menuHoverBackground
|
||||||
MenuBar.itemMargins = 3,8,3,8
|
MenuBar.itemMargins = 3,8,3,8
|
||||||
|
MenuBar.selectionInsets = $MenuItem.selectionInsets
|
||||||
|
MenuBar.selectionEmbeddedInsets = $MenuItem.selectionInsets
|
||||||
|
MenuBar.selectionArc = $MenuItem.selectionArc
|
||||||
|
|
||||||
|
|
||||||
#---- MenuItem ----
|
#---- MenuItem ----
|
||||||
@@ -444,6 +454,8 @@ MenuItem.textNoAcceleratorGap = 6
|
|||||||
MenuItem.acceleratorArrowGap = 2
|
MenuItem.acceleratorArrowGap = 2
|
||||||
MenuItem.acceleratorDelimiter = "+"
|
MenuItem.acceleratorDelimiter = "+"
|
||||||
[mac]MenuItem.acceleratorDelimiter = ""
|
[mac]MenuItem.acceleratorDelimiter = ""
|
||||||
|
MenuItem.selectionInsets = 0,0,0,0
|
||||||
|
MenuItem.selectionArc = 0
|
||||||
|
|
||||||
# for MenuItem.selectionType = underline
|
# for MenuItem.selectionType = underline
|
||||||
MenuItem.underlineSelectionBackground = @menuHoverBackground
|
MenuItem.underlineSelectionBackground = @menuHoverBackground
|
||||||
@@ -492,6 +504,7 @@ PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
|||||||
|
|
||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
|
|
||||||
|
Popup.borderCornerRadius = 4
|
||||||
Popup.dropShadowPainted = true
|
Popup.dropShadowPainted = true
|
||||||
Popup.dropShadowInsets = -4,-4,4,4
|
Popup.dropShadowInsets = -4,-4,4,4
|
||||||
|
|
||||||
@@ -500,6 +513,7 @@ Popup.dropShadowInsets = -4,-4,4,4
|
|||||||
|
|
||||||
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
||||||
PopupMenu.borderInsets = 4,1,4,1
|
PopupMenu.borderInsets = 4,1,4,1
|
||||||
|
PopupMenu.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
PopupMenu.background = @menuBackground
|
PopupMenu.background = @menuBackground
|
||||||
PopupMenu.scrollArrowColor = @buttonArrowColor
|
PopupMenu.scrollArrowColor = @buttonArrowColor
|
||||||
|
|
||||||
@@ -847,6 +861,7 @@ ToolBar.borderMargins = 2,2,2,2
|
|||||||
ToolBar.isRollover = true
|
ToolBar.isRollover = true
|
||||||
ToolBar.focusableButtons = false
|
ToolBar.focusableButtons = false
|
||||||
ToolBar.arrowKeysOnlyNavigation = true
|
ToolBar.arrowKeysOnlyNavigation = true
|
||||||
|
ToolBar.hoverButtonGroupArc = 8
|
||||||
ToolBar.floatable = false
|
ToolBar.floatable = false
|
||||||
ToolBar.gripColor = @icon
|
ToolBar.gripColor = @icon
|
||||||
ToolBar.dockingBackground = darken($ToolBar.background,5%)
|
ToolBar.dockingBackground = darken($ToolBar.background,5%)
|
||||||
@@ -868,6 +883,11 @@ ToolBar.spacingBorder = $Button.toolbar.spacingInsets
|
|||||||
ToolTipManager.enableToolTipMode = activeApplication
|
ToolTipManager.enableToolTipMode = activeApplication
|
||||||
|
|
||||||
|
|
||||||
|
#---- ToolTip ----
|
||||||
|
|
||||||
|
ToolTip.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
|
|
||||||
|
|
||||||
#---- Tree ----
|
#---- Tree ----
|
||||||
|
|
||||||
Tree.border = 1,1,1,1
|
Tree.border = 1,1,1,1
|
||||||
@@ -883,10 +903,13 @@ Tree.dropCellForeground = @dropCellForeground
|
|||||||
Tree.dropLineColor = @dropLineColor
|
Tree.dropLineColor = @dropLineColor
|
||||||
Tree.rendererFillBackground = false
|
Tree.rendererFillBackground = false
|
||||||
Tree.rendererMargins = 1,2,1,2
|
Tree.rendererMargins = 1,2,1,2
|
||||||
|
Tree.selectionInsets = 0,0,0,0
|
||||||
|
Tree.selectionArc = 0
|
||||||
Tree.wideSelection = true
|
Tree.wideSelection = true
|
||||||
Tree.repaintWholeRow = true
|
Tree.repaintWholeRow = true
|
||||||
Tree.paintLines = false
|
Tree.paintLines = false
|
||||||
Tree.showCellFocusIndicator = false
|
Tree.showCellFocusIndicator = false
|
||||||
|
Tree.showDefaultIcons = false
|
||||||
Tree.leftChildIndent = 7
|
Tree.leftChildIndent = 7
|
||||||
Tree.rightChildIndent = 11
|
Tree.rightChildIndent = 11
|
||||||
Tree.rowHeight = 0
|
Tree.rowHeight = 0
|
||||||
@@ -904,7 +927,6 @@ Tree.icon.closedColor = @icon
|
|||||||
Tree.icon.openColor = @icon
|
Tree.icon.openColor = @icon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---- Styles ------------------------------------------------------------------
|
#---- Styles ------------------------------------------------------------------
|
||||||
|
|
||||||
#---- inTextField ----
|
#---- inTextField ----
|
||||||
|
|||||||
@@ -50,19 +50,20 @@
|
|||||||
@selectionInactiveForeground = @foreground
|
@selectionInactiveForeground = @foreground
|
||||||
|
|
||||||
# menu
|
# menu
|
||||||
|
@menuSelectionBackground = @selectionBackground
|
||||||
@menuHoverBackground = darken(@menuBackground,10%,derived)
|
@menuHoverBackground = darken(@menuBackground,10%,derived)
|
||||||
@menuCheckBackground = lighten(@selectionBackground,40%,derived noAutoInverse)
|
@menuCheckBackground = lighten(@menuSelectionBackground,40%,derived noAutoInverse)
|
||||||
@menuAcceleratorForeground = lighten(@foreground,30%)
|
@menuAcceleratorForeground = lighten(@foreground,30%)
|
||||||
@menuAcceleratorSelectionForeground = @selectionForeground
|
@menuAcceleratorSelectionForeground = @selectionForeground
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
@cellFocusColor = #000
|
@cellFocusColor = darken(@selectionBackground,20%)
|
||||||
@icon = shade(@background,27%)
|
@icon = shade(@background,27%)
|
||||||
|
|
||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
# set @accentColor to use single accent color or
|
# set @accentColor to use single accent color or
|
||||||
# modify @accentBaseColor to use variations of accent base color
|
# modify @accentBaseColor to use variations of accent base color
|
||||||
@accentColor = null
|
@accentColor = systemColor(accent,null)
|
||||||
@accentBaseColor = #2675BF
|
@accentBaseColor = #2675BF
|
||||||
@accentBase2Color = lighten(saturate(@accentBaseColor,10%),6%)
|
@accentBase2Color = lighten(saturate(@accentBaseColor,10%),6%)
|
||||||
# accent color variations
|
# accent color variations
|
||||||
@@ -337,6 +338,8 @@ Table.gridColor = darken($Table.background,8%)
|
|||||||
|
|
||||||
#---- TableHeader ----
|
#---- TableHeader ----
|
||||||
|
|
||||||
|
TableHeader.hoverBackground = darken($TableHeader.background,5%,derived)
|
||||||
|
TableHeader.pressedBackground = darken($TableHeader.background,10%,derived)
|
||||||
TableHeader.separatorColor = darken($TableHeader.background,10%)
|
TableHeader.separatorColor = darken($TableHeader.background,10%)
|
||||||
TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||||
|
|
||||||
@@ -356,6 +359,11 @@ ToggleButton.disabledSelectedBackground = darken($ToggleButton.background,13%,de
|
|||||||
ToggleButton.toolbar.selectedBackground = $ToggleButton.selectedBackground
|
ToggleButton.toolbar.selectedBackground = $ToggleButton.selectedBackground
|
||||||
|
|
||||||
|
|
||||||
|
#---- ToolBar ----
|
||||||
|
|
||||||
|
ToolBar.hoverButtonGroupBackground = darken($ToolBar.background,3%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToolTip ----
|
#---- ToolTip ----
|
||||||
|
|
||||||
ToolTip.border = 4,6,4,6,shade(@background,40%)
|
ToolTip.border = 4,6,4,6,shade(@background,40%)
|
||||||
|
|||||||
@@ -44,6 +44,15 @@ info = lazy(ToolTip.background)
|
|||||||
infoText = lazy(ToolTip.foreground)
|
infoText = lazy(ToolTip.foreground)
|
||||||
|
|
||||||
|
|
||||||
|
#---- variables ----
|
||||||
|
|
||||||
|
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
|
||||||
|
@accentColor = null
|
||||||
|
|
||||||
|
# use fixed color because it is used in borders
|
||||||
|
@cellFocusColor = #222
|
||||||
|
|
||||||
|
|
||||||
#---- Button ----
|
#---- Button ----
|
||||||
|
|
||||||
Button.startBackground = $Button.background
|
Button.startBackground = $Button.background
|
||||||
@@ -213,6 +222,7 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
||||||
|
|
||||||
|
[Solarized_Light---4lex4]Button.default.hoverBackground = darken($Button.default.background,3%,derived)
|
||||||
[Solarized_Light---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Solarized_Light---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
|
|
||||||
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2022 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# base theme (light, dark, intellij or darcula); only used by theme editor
|
||||||
|
@baseTheme = dark
|
||||||
|
|
||||||
|
|
||||||
|
#---- macOS NSColor system colors (in NSColorSpace.deviceRGB) ----
|
||||||
|
# generated on macOS 12.2 using Xcode and flatlaf-testing/misc/MacOSColorDump.playground
|
||||||
|
|
||||||
|
@nsLabelColor = #ffffffd8
|
||||||
|
@nsSecondaryLabelColor = #ffffff8c
|
||||||
|
@nsTertiaryLabelColor = #ffffff3f
|
||||||
|
@nsQuaternaryLabelColor = #ffffff19
|
||||||
|
@nsSystemRedColor = #ff453a
|
||||||
|
@nsSystemGreenColor = #32d74b
|
||||||
|
@nsSystemBlueColor = #0a84ff
|
||||||
|
@nsSystemOrangeColor = #ff9f0a
|
||||||
|
@nsSystemYellowColor = #ffd60a
|
||||||
|
@nsSystemBrownColor = #ac8e68
|
||||||
|
@nsSystemPinkColor = #ff375f
|
||||||
|
@nsSystemPurpleColor = #bf5af2
|
||||||
|
@nsSystemTealColor = #6ac4dc
|
||||||
|
@nsSystemIndigoColor = #5e5ce6
|
||||||
|
@nsSystemMintColor = #63e6e2
|
||||||
|
@nsSystemCyanColor = #5ac8f5
|
||||||
|
@nsSystemGrayColor = #98989d
|
||||||
|
@nsLinkColor = #419cff
|
||||||
|
@nsPlaceholderTextColor = #ffffff3f
|
||||||
|
@nsWindowFrameTextColor = #ffffffd8
|
||||||
|
@nsSelectedMenuItemTextColor = #ffffff
|
||||||
|
@nsAlternateSelectedControlTextColor = #ffffff
|
||||||
|
@nsHeaderTextColor = #ffffff
|
||||||
|
@nsSeparatorColor = #ffffff19
|
||||||
|
@nsGridColor = #1a1a1a
|
||||||
|
@nsTextColor = #ffffff
|
||||||
|
@nsTextBackgroundColor = #1e1e1e
|
||||||
|
@nsSelectedTextColor = #ffffff
|
||||||
|
@nsSelectedTextBackgroundColor = #3f638b
|
||||||
|
@nsUnemphasizedSelectedTextBackgroundColor = #464646
|
||||||
|
@nsUnemphasizedSelectedTextColor = #ffffff
|
||||||
|
@nsWindowBackgroundColor = #323232
|
||||||
|
@nsUnderPageBackgroundColor = #282828
|
||||||
|
@nsControlBackgroundColor = #1e1e1e
|
||||||
|
@nsSelectedContentBackgroundColor = #0058d0
|
||||||
|
@nsUnemphasizedSelectedContentBackgroundColor = #464646
|
||||||
|
@nsFindHighlightColor = #ffff00
|
||||||
|
@nsControlColor = #ffffff3f
|
||||||
|
@nsControlTextColor = #ffffffd8
|
||||||
|
@nsSelectedControlColor = #3f638b
|
||||||
|
@nsSelectedControlTextColor = #ffffffd8
|
||||||
|
@nsDisabledControlTextColor = #ffffff3f
|
||||||
|
@nsKeyboardFocusIndicatorColor = #1aa9ff7f
|
||||||
|
@nsControlAccentColor = #007aff
|
||||||
|
|
||||||
|
# accent colors are:
|
||||||
|
# @nsSelectedTextBackgroundColor
|
||||||
|
# @nsSelectedContentBackgroundColor
|
||||||
|
# @nsSelectedControlColor
|
||||||
|
# @nsKeyboardFocusIndicatorColor
|
||||||
|
# @nsControlAccentColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- variables ----
|
||||||
|
|
||||||
|
# general background and foreground (text color)
|
||||||
|
@background = @nsControlBackgroundColor
|
||||||
|
@foreground = over(@nsControlTextColor,@background)
|
||||||
|
@disabledForeground = over(@nsSecondaryLabelColor,@background)
|
||||||
|
|
||||||
|
# component background
|
||||||
|
@buttonBackground = over(@nsControlColor,@background)
|
||||||
|
@componentBackground = darken(over(@nsControlColor,@background),18%)
|
||||||
|
@disabledComponentBackground = darken(@componentBackground,2%)
|
||||||
|
@menuBackground = lighten(@background,8%)
|
||||||
|
|
||||||
|
# selection
|
||||||
|
@selectionBackground = if(systemColor(accent), shade(spin(systemColor(accent),4),20%), @nsSelectedContentBackgroundColor)
|
||||||
|
@selectionForeground = @nsSelectedMenuItemTextColor
|
||||||
|
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
||||||
|
|
||||||
|
# text selection
|
||||||
|
@textSelectionBackground = systemColor(highlight,if(systemColor(accent), darken(desaturate(systemColor(accent),60%),10%), @nsSelectedTextBackgroundColor))
|
||||||
|
@textSelectionForeground = @nsSelectedTextColor
|
||||||
|
|
||||||
|
# menu
|
||||||
|
@menuSelectionBackground = desaturate(@selectionBackground,20%)
|
||||||
|
@menuItemMargin = 3,11,3,11
|
||||||
|
|
||||||
|
# accent colors (blueish)
|
||||||
|
@accentColor = systemColor(accent,@nsControlAccentColor)
|
||||||
|
@accentFocusColor = if(systemColor(accent), fade(spin(systemColor(accent),-10),50%), @nsKeyboardFocusIndicatorColor)
|
||||||
|
|
||||||
|
|
||||||
|
#---- Button ----
|
||||||
|
|
||||||
|
Button.arc = 12
|
||||||
|
Button.borderWidth = 0
|
||||||
|
Button.disabledBackground = darken($Button.background,10%)
|
||||||
|
|
||||||
|
Button.default.borderWidth = 0
|
||||||
|
|
||||||
|
Button.toolbar.hoverBackground = #fff1
|
||||||
|
Button.toolbar.pressedBackground = #fff2
|
||||||
|
Button.toolbar.selectedBackground = #fff3
|
||||||
|
|
||||||
|
|
||||||
|
#---- CheckBox ----
|
||||||
|
|
||||||
|
CheckBox.iconTextGap = 6
|
||||||
|
CheckBox.arc = 7
|
||||||
|
CheckBox.icon.focusWidth = null
|
||||||
|
CheckBox.icon.style = filled
|
||||||
|
CheckBox.icon[filled].borderWidth = 0
|
||||||
|
CheckBox.icon[filled].selectedBorderWidth = 0
|
||||||
|
CheckBox.icon[filled].background = darken(over(@nsControlColor,@background),3%)
|
||||||
|
CheckBox.icon[filled].disabledBackground = darken($CheckBox.icon[filled].background,10%)
|
||||||
|
CheckBox.icon[filled].selectedBackground = @accentColor
|
||||||
|
CheckBox.icon[filled].checkmarkColor = fadeout(@nsSelectedMenuItemTextColor,15%)
|
||||||
|
CheckBox.icon[filled].disabledCheckmarkColor = darken($CheckBox.icon[filled].checkmarkColor,45%)
|
||||||
|
CheckBox.icon.focusedBackground = null
|
||||||
|
|
||||||
|
|
||||||
|
#---- ComboBox ----
|
||||||
|
|
||||||
|
ComboBox.buttonStyle = mac
|
||||||
|
ComboBox.background = over(@nsControlColor,@background)
|
||||||
|
ComboBox.editableBackground = @componentBackground
|
||||||
|
ComboBox.disabledBackground = @disabledComponentBackground
|
||||||
|
ComboBox.buttonBackground = @accentColor
|
||||||
|
ComboBox.buttonArrowColor = @nsSelectedMenuItemTextColor
|
||||||
|
ComboBox.buttonHoverArrowColor = darken($ComboBox.buttonArrowColor,15%,derived noAutoInverse)
|
||||||
|
ComboBox.buttonPressedArrowColor = darken($ComboBox.buttonArrowColor,25%,derived noAutoInverse)
|
||||||
|
ComboBox.popupBackground = @menuBackground
|
||||||
|
ComboBox.selectionBackground = @menuSelectionBackground
|
||||||
|
ComboBox.popupInsets = 5,0,5,0
|
||||||
|
ComboBox.selectionInsets = 0,5,0,5
|
||||||
|
ComboBox.selectionArc = 8
|
||||||
|
ComboBox.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
|
#---- Component ----
|
||||||
|
|
||||||
|
Component.focusWidth = 2
|
||||||
|
Component.innerFocusWidth = 0
|
||||||
|
Component.innerOutlineWidth = 0
|
||||||
|
Component.arc = 12
|
||||||
|
Component.borderColor = @nsSeparatorColor
|
||||||
|
Component.disabledBorderColor = fadeout(@nsSeparatorColor,5%)
|
||||||
|
|
||||||
|
|
||||||
|
#---- EditorPane ---
|
||||||
|
|
||||||
|
EditorPane.disabledBackground = @disabledComponentBackground
|
||||||
|
EditorPane.selectionBackground = @textSelectionBackground
|
||||||
|
EditorPane.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- FormattedTextField ---
|
||||||
|
|
||||||
|
FormattedTextField.disabledBackground = @disabledComponentBackground
|
||||||
|
FormattedTextField.selectionBackground = @textSelectionBackground
|
||||||
|
FormattedTextField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- MenuBar ----
|
||||||
|
|
||||||
|
MenuBar.selectionInsets = 0,0,0,0
|
||||||
|
MenuBar.selectionEmbeddedInsets = 3,0,3,0
|
||||||
|
MenuBar.selectionArc = 8
|
||||||
|
MenuBar.selectionBackground = lighten(@menuBackground,15%,derived)
|
||||||
|
MenuBar.selectionForeground = @foreground
|
||||||
|
|
||||||
|
|
||||||
|
#---- MenuItem ----
|
||||||
|
|
||||||
|
MenuItem.selectionInsets = 0,5,0,5
|
||||||
|
MenuItem.selectionArc = 8
|
||||||
|
|
||||||
|
Menu.selectionBackground = @menuSelectionBackground
|
||||||
|
MenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
CheckBoxMenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
RadioButtonMenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
|
||||||
|
|
||||||
|
#---- PasswordField ---
|
||||||
|
|
||||||
|
PasswordField.disabledBackground = @disabledComponentBackground
|
||||||
|
PasswordField.selectionBackground = @textSelectionBackground
|
||||||
|
PasswordField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- PopupMenu ----
|
||||||
|
|
||||||
|
PopupMenu.borderInsets = 6,1,6,1
|
||||||
|
PopupMenu.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
|
#---- ProgressBar ----
|
||||||
|
|
||||||
|
ProgressBar.background = lighten(@background,8%)
|
||||||
|
|
||||||
|
|
||||||
|
#---- RadioButton ----
|
||||||
|
|
||||||
|
RadioButton.iconTextGap = 6
|
||||||
|
RadioButton.icon.style = filled
|
||||||
|
RadioButton.icon[filled].centerDiameter = 6
|
||||||
|
|
||||||
|
|
||||||
|
#---- ScrollBar ----
|
||||||
|
|
||||||
|
ScrollBar.width = 12
|
||||||
|
ScrollBar.track = @componentBackground
|
||||||
|
ScrollBar.thumb = @buttonBackground
|
||||||
|
|
||||||
|
# from FlatLaf.properties (when using not on macOS)
|
||||||
|
ScrollBar.minimumThumbSize = 18,18
|
||||||
|
ScrollBar.thumbInsets = 2,2,2,2
|
||||||
|
ScrollBar.thumbArc = 999
|
||||||
|
ScrollBar.hoverThumbWithTrack = true
|
||||||
|
|
||||||
|
|
||||||
|
#---- Separator ----
|
||||||
|
|
||||||
|
Separator.foreground = @nsSeparatorColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- Slider ----
|
||||||
|
|
||||||
|
Slider.trackWidth = 3
|
||||||
|
Slider.thumbSize = 14,14
|
||||||
|
Slider.trackColor = lighten(@background,8%)
|
||||||
|
Slider.thumbColor = lighten($Slider.trackColor,35%)
|
||||||
|
Slider.disabledTrackColor = darken($Slider.trackColor,4%)
|
||||||
|
Slider.disabledThumbColor = darken($Slider.thumbColor,32%)
|
||||||
|
Slider.focusedColor = $Component.focusColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- Spinner ----
|
||||||
|
|
||||||
|
Spinner.buttonStyle = mac
|
||||||
|
Spinner.disabledBackground = @disabledComponentBackground
|
||||||
|
Spinner.buttonBackground = @buttonBackground
|
||||||
|
Spinner.buttonArrowColor = @foreground
|
||||||
|
Spinner.buttonHoverArrowColor = lighten($Spinner.buttonArrowColor,10%,derived noAutoInverse)
|
||||||
|
Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,20%,derived noAutoInverse)
|
||||||
|
Spinner.buttonSeparatorWidth = 0
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextArea ---
|
||||||
|
|
||||||
|
TextArea.disabledBackground = @disabledComponentBackground
|
||||||
|
TextArea.selectionBackground = @textSelectionBackground
|
||||||
|
TextArea.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextField ----
|
||||||
|
|
||||||
|
TextField.disabledBackground = @disabledComponentBackground
|
||||||
|
TextField.selectionBackground = @textSelectionBackground
|
||||||
|
TextField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextPane ---
|
||||||
|
|
||||||
|
TextPane.disabledBackground = @disabledComponentBackground
|
||||||
|
TextPane.selectionBackground = @textSelectionBackground
|
||||||
|
TextPane.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- ToggleButton ----
|
||||||
|
|
||||||
|
ToggleButton.disabledBackground = $Button.disabledBackground
|
||||||
|
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
||||||
|
|
||||||
|
ToggleButton.toolbar.selectedBackground = #fff3
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2022 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# base theme (light, dark, intellij or darcula); only used by theme editor
|
||||||
|
@baseTheme = light
|
||||||
|
|
||||||
|
|
||||||
|
#---- macOS NSColor system colors (in NSColorSpace.deviceRGB) ----
|
||||||
|
# generated on macOS 12.2 using Xcode and flatlaf-testing/misc/MacOSColorDump.playground
|
||||||
|
|
||||||
|
@nsLabelColor = #000000d8
|
||||||
|
@nsSecondaryLabelColor = #0000007f
|
||||||
|
@nsTertiaryLabelColor = #00000042
|
||||||
|
@nsQuaternaryLabelColor = #00000019
|
||||||
|
@nsSystemRedColor = #ff3b30
|
||||||
|
@nsSystemGreenColor = #28cd41
|
||||||
|
@nsSystemBlueColor = #007aff
|
||||||
|
@nsSystemOrangeColor = #ff9500
|
||||||
|
@nsSystemYellowColor = #ffcc00
|
||||||
|
@nsSystemBrownColor = #a2845e
|
||||||
|
@nsSystemPinkColor = #ff2d55
|
||||||
|
@nsSystemPurpleColor = #af52de
|
||||||
|
@nsSystemTealColor = #59adc4
|
||||||
|
@nsSystemIndigoColor = #5856d6
|
||||||
|
@nsSystemMintColor = #00c7be
|
||||||
|
@nsSystemCyanColor = #55bef0
|
||||||
|
@nsSystemGrayColor = #8e8e93
|
||||||
|
@nsLinkColor = #0068da
|
||||||
|
@nsPlaceholderTextColor = #0000003f
|
||||||
|
@nsWindowFrameTextColor = #000000d8
|
||||||
|
@nsSelectedMenuItemTextColor = #ffffff
|
||||||
|
@nsAlternateSelectedControlTextColor = #ffffff
|
||||||
|
@nsHeaderTextColor = #000000d8
|
||||||
|
@nsSeparatorColor = #00000019
|
||||||
|
@nsGridColor = #e6e6e6
|
||||||
|
@nsTextColor = #000000
|
||||||
|
@nsTextBackgroundColor = #ffffff
|
||||||
|
@nsSelectedTextColor = #000000
|
||||||
|
@nsSelectedTextBackgroundColor = #b3d7ff
|
||||||
|
@nsUnemphasizedSelectedTextBackgroundColor = #dcdcdc
|
||||||
|
@nsUnemphasizedSelectedTextColor = #000000
|
||||||
|
@nsWindowBackgroundColor = #ececec
|
||||||
|
@nsUnderPageBackgroundColor = #969696e5
|
||||||
|
@nsControlBackgroundColor = #ffffff
|
||||||
|
@nsSelectedContentBackgroundColor = #0063e1
|
||||||
|
@nsUnemphasizedSelectedContentBackgroundColor = #dcdcdc
|
||||||
|
@nsFindHighlightColor = #ffff00
|
||||||
|
@nsControlColor = #ffffff
|
||||||
|
@nsControlTextColor = #000000d8
|
||||||
|
@nsSelectedControlColor = #b3d7ff
|
||||||
|
@nsSelectedControlTextColor = #000000d8
|
||||||
|
@nsDisabledControlTextColor = #0000003f
|
||||||
|
@nsKeyboardFocusIndicatorColor = #0067f47f
|
||||||
|
@nsControlAccentColor = #007aff
|
||||||
|
|
||||||
|
# accent colors are:
|
||||||
|
# @nsSelectedTextBackgroundColor
|
||||||
|
# @nsSelectedContentBackgroundColor
|
||||||
|
# @nsSelectedControlColor
|
||||||
|
# @nsKeyboardFocusIndicatorColor
|
||||||
|
# @nsControlAccentColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- variables ----
|
||||||
|
|
||||||
|
# general background and foreground (text color)
|
||||||
|
@background = #f6f6f6
|
||||||
|
@foreground = over(@nsControlTextColor,@background)
|
||||||
|
@disabledForeground = over(@nsTertiaryLabelColor,@background)
|
||||||
|
|
||||||
|
# component background
|
||||||
|
@buttonBackground = @nsControlColor
|
||||||
|
@componentBackground = @nsControlColor
|
||||||
|
@disabledComponentBackground = darken(@componentBackground,2%)
|
||||||
|
@menuBackground = darken(@background,4%)
|
||||||
|
|
||||||
|
# selection
|
||||||
|
@selectionBackground = if(systemColor(accent), shade(spin(systemColor(accent),4),10%), @nsSelectedContentBackgroundColor)
|
||||||
|
@selectionForeground = @nsSelectedMenuItemTextColor
|
||||||
|
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
||||||
|
|
||||||
|
# text selection
|
||||||
|
@textSelectionBackground = systemColor(highlight,if(systemColor(accent), tint(systemColor(accent),70%), @nsSelectedTextBackgroundColor))
|
||||||
|
@textSelectionForeground = @foreground
|
||||||
|
|
||||||
|
# menu
|
||||||
|
@menuSelectionBackground = lighten(@accentColor,12%)
|
||||||
|
@menuCheckBackground = lighten(@menuSelectionBackground,25%,derived noAutoInverse)
|
||||||
|
@menuItemMargin = 3,11,3,11
|
||||||
|
|
||||||
|
# accent colors (blueish)
|
||||||
|
@accentColor = systemColor(accent,@nsControlAccentColor)
|
||||||
|
@accentFocusColor = if(systemColor(accent), fade(spin(systemColor(accent),4),50%), @nsKeyboardFocusIndicatorColor)
|
||||||
|
|
||||||
|
|
||||||
|
#---- Button ----
|
||||||
|
|
||||||
|
Button.arc = 12
|
||||||
|
Button.disabledBackground = @disabledComponentBackground
|
||||||
|
Button.focusedBackground = null
|
||||||
|
|
||||||
|
Button.default.borderWidth = 1
|
||||||
|
Button.default.boldText = true
|
||||||
|
Button.default.background = @accentColor
|
||||||
|
Button.default.foreground = contrast($Button.default.background, @background, $Button.foreground, 20%)
|
||||||
|
|
||||||
|
|
||||||
|
#---- CheckBox ----
|
||||||
|
|
||||||
|
CheckBox.iconTextGap = 6
|
||||||
|
CheckBox.arc = 7
|
||||||
|
CheckBox.icon.focusWidth = null
|
||||||
|
CheckBox.icon.style = filled
|
||||||
|
CheckBox.icon[filled].borderWidth = 1
|
||||||
|
CheckBox.icon[filled].selectedBorderWidth = 0
|
||||||
|
CheckBox.icon[filled].disabledSelectedBorderWidth = 1
|
||||||
|
CheckBox.icon[filled].background = @nsControlColor
|
||||||
|
CheckBox.icon[filled].disabledBackground = @disabledComponentBackground
|
||||||
|
CheckBox.icon[filled].selectedBackground = @accentColor
|
||||||
|
CheckBox.icon[filled].borderColor = $Component.borderColor
|
||||||
|
CheckBox.icon[filled].disabledBorderColor = $Component.disabledBorderColor
|
||||||
|
CheckBox.icon[filled].checkmarkColor = @nsSelectedMenuItemTextColor
|
||||||
|
CheckBox.icon[filled].disabledCheckmarkColor = darken($CheckBox.icon[filled].checkmarkColor,25%)
|
||||||
|
CheckBox.icon.focusedBackground = null
|
||||||
|
|
||||||
|
|
||||||
|
#---- ComboBox ----
|
||||||
|
|
||||||
|
ComboBox.buttonStyle = mac
|
||||||
|
ComboBox.disabledBackground = @disabledComponentBackground
|
||||||
|
ComboBox.buttonBackground = @accentColor
|
||||||
|
ComboBox.buttonArrowColor = @nsSelectedMenuItemTextColor
|
||||||
|
ComboBox.buttonHoverArrowColor = darken($ComboBox.buttonArrowColor,15%,derived noAutoInverse)
|
||||||
|
ComboBox.buttonPressedArrowColor = darken($ComboBox.buttonArrowColor,25%,derived noAutoInverse)
|
||||||
|
ComboBox.popupBackground = @menuBackground
|
||||||
|
ComboBox.selectionBackground = @menuSelectionBackground
|
||||||
|
ComboBox.popupInsets = 5,0,5,0
|
||||||
|
ComboBox.selectionInsets = 0,5,0,5
|
||||||
|
ComboBox.selectionArc = 8
|
||||||
|
ComboBox.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
|
#---- Component ----
|
||||||
|
|
||||||
|
Component.focusWidth = 2
|
||||||
|
Component.innerFocusWidth = 0
|
||||||
|
Component.innerOutlineWidth = 0
|
||||||
|
Component.arc = 12
|
||||||
|
Component.borderColor = fadein(@nsSeparatorColor,5%)
|
||||||
|
Component.disabledBorderColor = @nsSeparatorColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- EditorPane ---
|
||||||
|
|
||||||
|
EditorPane.disabledBackground = @disabledComponentBackground
|
||||||
|
EditorPane.selectionBackground = @textSelectionBackground
|
||||||
|
EditorPane.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- FormattedTextField ---
|
||||||
|
|
||||||
|
FormattedTextField.disabledBackground = @disabledComponentBackground
|
||||||
|
FormattedTextField.selectionBackground = @textSelectionBackground
|
||||||
|
FormattedTextField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- MenuBar ----
|
||||||
|
|
||||||
|
MenuBar.selectionInsets = 0,0,0,0
|
||||||
|
MenuBar.selectionEmbeddedInsets = 3,0,3,0
|
||||||
|
MenuBar.selectionArc = 8
|
||||||
|
MenuBar.selectionBackground = darken(@menuBackground,15%,derived)
|
||||||
|
MenuBar.selectionForeground = @foreground
|
||||||
|
|
||||||
|
|
||||||
|
#---- MenuItem ----
|
||||||
|
|
||||||
|
MenuItem.selectionInsets = 0,5,0,5
|
||||||
|
MenuItem.selectionArc = 8
|
||||||
|
|
||||||
|
Menu.selectionBackground = @menuSelectionBackground
|
||||||
|
MenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
CheckBoxMenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
RadioButtonMenuItem.selectionBackground = @menuSelectionBackground
|
||||||
|
|
||||||
|
|
||||||
|
#---- PasswordField ---
|
||||||
|
|
||||||
|
PasswordField.disabledBackground = @disabledComponentBackground
|
||||||
|
PasswordField.selectionBackground = @textSelectionBackground
|
||||||
|
PasswordField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- PopupMenu ----
|
||||||
|
|
||||||
|
PopupMenu.borderInsets = 6,1,6,1
|
||||||
|
PopupMenu.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
|
#---- ProgressBar ----
|
||||||
|
|
||||||
|
ProgressBar.background = darken(@background,5%)
|
||||||
|
|
||||||
|
|
||||||
|
#---- RadioButton ----
|
||||||
|
|
||||||
|
RadioButton.iconTextGap = 6
|
||||||
|
RadioButton.icon.style = filled
|
||||||
|
RadioButton.icon[filled].centerDiameter = 6
|
||||||
|
|
||||||
|
|
||||||
|
#---- ScrollBar ----
|
||||||
|
|
||||||
|
ScrollBar.width = 12
|
||||||
|
ScrollBar.track = darken(@componentBackground,2%)
|
||||||
|
ScrollBar.thumb = darken(@componentBackground,24%)
|
||||||
|
|
||||||
|
# from FlatLaf.properties (when using not on macOS)
|
||||||
|
ScrollBar.minimumThumbSize = 18,18
|
||||||
|
ScrollBar.thumbInsets = 2,2,2,2
|
||||||
|
ScrollBar.thumbArc = 999
|
||||||
|
ScrollBar.hoverThumbWithTrack = true
|
||||||
|
|
||||||
|
|
||||||
|
#---- Separator ----
|
||||||
|
|
||||||
|
Separator.foreground = @nsSeparatorColor
|
||||||
|
|
||||||
|
|
||||||
|
#---- Slider ----
|
||||||
|
|
||||||
|
Slider.trackWidth = 3
|
||||||
|
Slider.thumbSize = 14,14
|
||||||
|
Slider.trackColor = darken(@background,7%)
|
||||||
|
Slider.thumbColor = @componentBackground
|
||||||
|
Slider.thumbBorderColor = $Component.borderColor
|
||||||
|
Slider.disabledTrackColor = lighten($Slider.trackColor,3%)
|
||||||
|
Slider.disabledThumbColor = darken($Slider.thumbColor,3%)
|
||||||
|
|
||||||
|
|
||||||
|
#---- Spinner ----
|
||||||
|
|
||||||
|
Spinner.buttonStyle = mac
|
||||||
|
Spinner.disabledBackground = @disabledComponentBackground
|
||||||
|
Spinner.buttonArrowColor = @foreground
|
||||||
|
Spinner.buttonHoverArrowColor = lighten($Spinner.buttonArrowColor,20%,derived noAutoInverse)
|
||||||
|
Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,30%,derived noAutoInverse)
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextArea ---
|
||||||
|
|
||||||
|
TextArea.disabledBackground = @disabledComponentBackground
|
||||||
|
TextArea.selectionBackground = @textSelectionBackground
|
||||||
|
TextArea.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextField ----
|
||||||
|
|
||||||
|
TextField.disabledBackground = @disabledComponentBackground
|
||||||
|
TextField.selectionBackground = @textSelectionBackground
|
||||||
|
TextField.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- TextPane ---
|
||||||
|
|
||||||
|
TextPane.disabledBackground = @disabledComponentBackground
|
||||||
|
TextPane.selectionBackground = @textSelectionBackground
|
||||||
|
TextPane.selectionForeground = @textSelectionForeground
|
||||||
|
|
||||||
|
|
||||||
|
#---- ToggleButton ----
|
||||||
|
|
||||||
|
ToggleButton.disabledBackground = $Button.disabledBackground
|
||||||
@@ -185,7 +185,10 @@ public class TestFlatStyleableInfo
|
|||||||
"buttonHoverArrowColor", Color.class,
|
"buttonHoverArrowColor", Color.class,
|
||||||
"buttonPressedArrowColor", Color.class,
|
"buttonPressedArrowColor", Color.class,
|
||||||
|
|
||||||
"popupBackground", Color.class
|
"popupBackground", Color.class,
|
||||||
|
"popupInsets", Insets.class,
|
||||||
|
"selectionInsets", Insets.class,
|
||||||
|
"selectionArc", int.class
|
||||||
);
|
);
|
||||||
|
|
||||||
// border
|
// border
|
||||||
@@ -266,6 +269,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,
|
||||||
|
|
||||||
// FlatListCellBorder
|
// FlatListCellBorder
|
||||||
"cellMargins", Insets.class,
|
"cellMargins", Insets.class,
|
||||||
@@ -283,6 +288,9 @@ public class TestFlatStyleableInfo
|
|||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
"itemMargins", Insets.class,
|
"itemMargins", Insets.class,
|
||||||
|
"selectionInsets", Insets.class,
|
||||||
|
"selectionEmbeddedInsets", Insets.class,
|
||||||
|
"selectionArc", int.class,
|
||||||
"hoverBackground", Color.class,
|
"hoverBackground", Color.class,
|
||||||
"selectionBackground", Color.class,
|
"selectionBackground", Color.class,
|
||||||
"selectionForeground", Color.class,
|
"selectionForeground", Color.class,
|
||||||
@@ -369,6 +377,9 @@ public class TestFlatStyleableInfo
|
|||||||
"checkBackground", Color.class,
|
"checkBackground", Color.class,
|
||||||
"checkMargins", Insets.class,
|
"checkMargins", Insets.class,
|
||||||
|
|
||||||
|
"selectionInsets", Insets.class,
|
||||||
|
"selectionArc", int.class,
|
||||||
|
|
||||||
"underlineSelectionBackground", Color.class,
|
"underlineSelectionBackground", Color.class,
|
||||||
"underlineSelectionCheckBackground", Color.class,
|
"underlineSelectionCheckBackground", Color.class,
|
||||||
"underlineSelectionColor", Color.class,
|
"underlineSelectionColor", Color.class,
|
||||||
@@ -710,7 +721,9 @@ public class TestFlatStyleableInfo
|
|||||||
"inactiveUnderlineColor", Color.class,
|
"inactiveUnderlineColor", Color.class,
|
||||||
"disabledUnderlineColor", Color.class,
|
"disabledUnderlineColor", Color.class,
|
||||||
"hoverColor", Color.class,
|
"hoverColor", Color.class,
|
||||||
|
"hoverForeground", Color.class,
|
||||||
"focusColor", Color.class,
|
"focusColor", Color.class,
|
||||||
|
"focusForeground", Color.class,
|
||||||
"tabSeparatorColor", Color.class,
|
"tabSeparatorColor", Color.class,
|
||||||
"contentAreaColor", Color.class,
|
"contentAreaColor", Color.class,
|
||||||
|
|
||||||
@@ -793,6 +806,10 @@ public class TestFlatStyleableInfo
|
|||||||
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
|
"hoverBackground", Color.class,
|
||||||
|
"hoverForeground", Color.class,
|
||||||
|
"pressedBackground", Color.class,
|
||||||
|
"pressedForeground", Color.class,
|
||||||
"bottomSeparatorColor", Color.class,
|
"bottomSeparatorColor", Color.class,
|
||||||
"height", int.class,
|
"height", int.class,
|
||||||
"sortIconPosition", String.class,
|
"sortIconPosition", String.class,
|
||||||
@@ -899,6 +916,8 @@ public class TestFlatStyleableInfo
|
|||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
"focusableButtons", boolean.class,
|
"focusableButtons", boolean.class,
|
||||||
"arrowKeysOnlyNavigation", boolean.class,
|
"arrowKeysOnlyNavigation", boolean.class,
|
||||||
|
"hoverButtonGroupArc", int.class,
|
||||||
|
"hoverButtonGroupBackground", Color.class,
|
||||||
|
|
||||||
"borderMargins", Insets.class,
|
"borderMargins", Insets.class,
|
||||||
"gripColor", Color.class
|
"gripColor", Color.class
|
||||||
@@ -931,6 +950,8 @@ public class TestFlatStyleableInfo
|
|||||||
"selectionInactiveBackground", Color.class,
|
"selectionInactiveBackground", Color.class,
|
||||||
"selectionInactiveForeground", Color.class,
|
"selectionInactiveForeground", Color.class,
|
||||||
"selectionBorderColor", Color.class,
|
"selectionBorderColor", Color.class,
|
||||||
|
"selectionInsets", Insets.class,
|
||||||
|
"selectionArc", int.class,
|
||||||
"wideSelection", boolean.class,
|
"wideSelection", boolean.class,
|
||||||
"showCellFocusIndicator", boolean.class,
|
"showCellFocusIndicator", boolean.class,
|
||||||
|
|
||||||
|
|||||||
@@ -727,7 +727,9 @@ public class TestFlatStyleableValue
|
|||||||
testColor( c, ui, "inactiveUnderlineColor", 0x123456 );
|
testColor( c, ui, "inactiveUnderlineColor", 0x123456 );
|
||||||
testColor( c, ui, "disabledUnderlineColor", 0x123456 );
|
testColor( c, ui, "disabledUnderlineColor", 0x123456 );
|
||||||
testColor( c, ui, "hoverColor", 0x123456 );
|
testColor( c, ui, "hoverColor", 0x123456 );
|
||||||
|
testColor( c, ui, "hoverForeground", 0x123456 );
|
||||||
testColor( c, ui, "focusColor", 0x123456 );
|
testColor( c, ui, "focusColor", 0x123456 );
|
||||||
|
testColor( c, ui, "focusForeground", 0x123456 );
|
||||||
testColor( c, ui, "tabSeparatorColor", 0x123456 );
|
testColor( c, ui, "tabSeparatorColor", 0x123456 );
|
||||||
testColor( c, ui, "contentAreaColor", 0x123456 );
|
testColor( c, ui, "contentAreaColor", 0x123456 );
|
||||||
|
|
||||||
@@ -802,6 +804,10 @@ public class TestFlatStyleableValue
|
|||||||
JTableHeader c = new JTableHeader();
|
JTableHeader c = new JTableHeader();
|
||||||
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
||||||
|
|
||||||
|
testColor( c, ui, "hoverBackground", 0x123456 );
|
||||||
|
testColor( c, ui, "hoverForeground", 0x123456 );
|
||||||
|
testColor( c, ui, "pressedBackground", 0x123456 );
|
||||||
|
testColor( c, ui, "pressedForeground", 0x123456 );
|
||||||
testColor( c, ui, "bottomSeparatorColor", 0x123456 );
|
testColor( c, ui, "bottomSeparatorColor", 0x123456 );
|
||||||
testInteger( c, ui, "height", 123 );
|
testInteger( c, ui, "height", 123 );
|
||||||
testString( c, ui, "sortIconPosition", "top" );
|
testString( c, ui, "sortIconPosition", "top" );
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import javax.swing.table.JTableHeader;
|
|||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.icons.*;
|
import com.formdev.flatlaf.icons.*;
|
||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
|
|
||||||
@@ -39,12 +40,20 @@ public class TestFlatStyling
|
|||||||
{
|
{
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void setup() {
|
static void setup() {
|
||||||
|
HashMap<String, String> globalExtraDefaults = new HashMap<>();
|
||||||
|
globalExtraDefaults.put( "@var1", "#f00" );
|
||||||
|
globalExtraDefaults.put( "@var2", "@var1" );
|
||||||
|
globalExtraDefaults.put( "var2Resolved", "@var2" );
|
||||||
|
FlatLaf.setGlobalExtraDefaults( globalExtraDefaults );
|
||||||
|
|
||||||
TestUtils.setup( false );
|
TestUtils.setup( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void cleanup() {
|
static void cleanup() {
|
||||||
TestUtils.cleanup();
|
TestUtils.cleanup();
|
||||||
|
|
||||||
|
FlatLaf.setGlobalExtraDefaults( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -171,6 +180,13 @@ public class TestFlatStyling
|
|||||||
"saturate(darken(@background,20%),10%)" );
|
"saturate(darken(@background,20%),10%)" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseRecursiveVariables() {
|
||||||
|
Color background = UIManager.getColor( "var2Resolved" );
|
||||||
|
|
||||||
|
testColorStyle( background.getRGB(), "@var2" );
|
||||||
|
}
|
||||||
|
|
||||||
private void testColorStyle( int expectedRGB, String style ) {
|
private void testColorStyle( int expectedRGB, String style ) {
|
||||||
testStyle( "background", new Color( expectedRGB, (expectedRGB & 0xff000000) != 0 ), style );
|
testStyle( "background", new Color( expectedRGB, (expectedRGB & 0xff000000) != 0 ), style );
|
||||||
}
|
}
|
||||||
@@ -316,6 +332,9 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "buttonPressedArrowColor: #fff" );
|
ui.applyStyle( "buttonPressedArrowColor: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( "popupBackground: #fff" );
|
ui.applyStyle( "popupBackground: #fff" );
|
||||||
|
ui.applyStyle( "popupInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionArc: 8" );
|
||||||
|
|
||||||
// border
|
// border
|
||||||
flatRoundBorder( style -> ui.applyStyle( style ) );
|
flatRoundBorder( style -> ui.applyStyle( style ) );
|
||||||
@@ -413,6 +432,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" );
|
||||||
|
|
||||||
// FlatListCellBorder
|
// FlatListCellBorder
|
||||||
ui.applyStyle( "cellMargins: 1,2,3,4" );
|
ui.applyStyle( "cellMargins: 1,2,3,4" );
|
||||||
@@ -435,6 +456,9 @@ public class TestFlatStyling
|
|||||||
FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI();
|
FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI();
|
||||||
|
|
||||||
ui.applyStyle( "itemMargins: 1,2,3,4" );
|
ui.applyStyle( "itemMargins: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionEmbeddedInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionArc: 8" );
|
||||||
ui.applyStyle( "hoverBackground: #fff" );
|
ui.applyStyle( "hoverBackground: #fff" );
|
||||||
ui.applyStyle( "selectionBackground: #fff" );
|
ui.applyStyle( "selectionBackground: #fff" );
|
||||||
ui.applyStyle( "selectionForeground: #fff" );
|
ui.applyStyle( "selectionForeground: #fff" );
|
||||||
@@ -523,6 +547,9 @@ public class TestFlatStyling
|
|||||||
applyStyle.accept( "checkBackground: #fff" );
|
applyStyle.accept( "checkBackground: #fff" );
|
||||||
applyStyle.accept( "checkMargins: 1,2,3,4" );
|
applyStyle.accept( "checkMargins: 1,2,3,4" );
|
||||||
|
|
||||||
|
applyStyle.accept( "selectionInsets: 1,2,3,4" );
|
||||||
|
applyStyle.accept( "selectionArc: 8" );
|
||||||
|
|
||||||
applyStyle.accept( "underlineSelectionBackground: #fff" );
|
applyStyle.accept( "underlineSelectionBackground: #fff" );
|
||||||
applyStyle.accept( "underlineSelectionCheckBackground: #fff" );
|
applyStyle.accept( "underlineSelectionCheckBackground: #fff" );
|
||||||
applyStyle.accept( "underlineSelectionColor: #fff" );
|
applyStyle.accept( "underlineSelectionColor: #fff" );
|
||||||
@@ -879,7 +906,9 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "inactiveUnderlineColor: #fff" );
|
ui.applyStyle( "inactiveUnderlineColor: #fff" );
|
||||||
ui.applyStyle( "disabledUnderlineColor: #fff" );
|
ui.applyStyle( "disabledUnderlineColor: #fff" );
|
||||||
ui.applyStyle( "hoverColor: #fff" );
|
ui.applyStyle( "hoverColor: #fff" );
|
||||||
|
ui.applyStyle( "hoverForeground: #fff" );
|
||||||
ui.applyStyle( "focusColor: #fff" );
|
ui.applyStyle( "focusColor: #fff" );
|
||||||
|
ui.applyStyle( "focusForeground: #fff" );
|
||||||
ui.applyStyle( "tabSeparatorColor: #fff" );
|
ui.applyStyle( "tabSeparatorColor: #fff" );
|
||||||
ui.applyStyle( "contentAreaColor: #fff" );
|
ui.applyStyle( "contentAreaColor: #fff" );
|
||||||
|
|
||||||
@@ -972,6 +1001,10 @@ public class TestFlatStyling
|
|||||||
JTableHeader c = new JTableHeader();
|
JTableHeader c = new JTableHeader();
|
||||||
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI();
|
||||||
|
|
||||||
|
ui.applyStyle( "hoverBackground: #fff" );
|
||||||
|
ui.applyStyle( "hoverForeground: #fff" );
|
||||||
|
ui.applyStyle( "pressedBackground: #fff" );
|
||||||
|
ui.applyStyle( "pressedForeground: #fff" );
|
||||||
ui.applyStyle( "bottomSeparatorColor: #fff" );
|
ui.applyStyle( "bottomSeparatorColor: #fff" );
|
||||||
ui.applyStyle( "height: 20" );
|
ui.applyStyle( "height: 20" );
|
||||||
ui.applyStyle( "sortIconPosition: top" );
|
ui.applyStyle( "sortIconPosition: top" );
|
||||||
@@ -1102,6 +1135,8 @@ public class TestFlatStyling
|
|||||||
|
|
||||||
ui.applyStyle( "focusableButtons: true" );
|
ui.applyStyle( "focusableButtons: true" );
|
||||||
ui.applyStyle( "arrowKeysOnlyNavigation: true" );
|
ui.applyStyle( "arrowKeysOnlyNavigation: true" );
|
||||||
|
ui.applyStyle( "hoverButtonGroupArc: 12" );
|
||||||
|
ui.applyStyle( "hoverButtonGroupBackground: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( "borderMargins: 1,2,3,4" );
|
ui.applyStyle( "borderMargins: 1,2,3,4" );
|
||||||
ui.applyStyle( "gripColor: #fff" );
|
ui.applyStyle( "gripColor: #fff" );
|
||||||
@@ -1137,6 +1172,8 @@ 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( "selectionInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "selectionArc: 8" );
|
||||||
ui.applyStyle( "wideSelection: true" );
|
ui.applyStyle( "wideSelection: true" );
|
||||||
ui.applyStyle( "showCellFocusIndicator: true" );
|
ui.applyStyle( "showCellFocusIndicator: true" );
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
|||||||
*/
|
*/
|
||||||
public class TestUtils
|
public class TestUtils
|
||||||
{
|
{
|
||||||
public static final float[] FACTORS = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
public static final float[] FACTORS = { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||||
|
|
||||||
public static void setup( boolean withFocus ) {
|
public static void setup( boolean withFocus ) {
|
||||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class TestColorFunctions
|
|||||||
{
|
{
|
||||||
@Test
|
@Test
|
||||||
void colorFunctions() {
|
void colorFunctions() {
|
||||||
|
// lighten, darken
|
||||||
assertEquals( new Color( 0xff6666 ), ColorFunctions.lighten( Color.red, 0.2f ) );
|
assertEquals( new Color( 0xff6666 ), ColorFunctions.lighten( Color.red, 0.2f ) );
|
||||||
assertEquals( new Color( 0x990000 ), ColorFunctions.darken( Color.red, 0.2f ) );
|
assertEquals( new Color( 0x990000 ), ColorFunctions.darken( Color.red, 0.2f ) );
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ public class TestColorFunctions
|
|||||||
assertEquals( new Color( 0xffaa00 ), ColorFunctions.spin( Color.red,40 ) );
|
assertEquals( new Color( 0xffaa00 ), ColorFunctions.spin( Color.red,40 ) );
|
||||||
assertEquals( new Color( 0xff00aa ), ColorFunctions.spin( Color.red,-40 ) );
|
assertEquals( new Color( 0xff00aa ), ColorFunctions.spin( Color.red,-40 ) );
|
||||||
|
|
||||||
|
// fade
|
||||||
|
assertEquals( new Color( 0x33ff0000, true ), ColorFunctions.fade( Color.red, 0.2f ) );
|
||||||
|
assertEquals( new Color( 0xccff0000, true ), ColorFunctions.fade( Color.red, 0.8f ) );
|
||||||
|
assertEquals( new Color( 0xccff0000, true ), ColorFunctions.fade( new Color( 0x10ff0000, true ), 0.8f ) );
|
||||||
|
|
||||||
// mix
|
// mix
|
||||||
assertEquals( new Color( 0x1ae600 ), ColorFunctions.mix( Color.red, Color.green, 0.1f ) );
|
assertEquals( new Color( 0x1ae600 ), ColorFunctions.mix( Color.red, Color.green, 0.1f ) );
|
||||||
assertEquals( new Color( 0x40bf00 ), ColorFunctions.mix( Color.red, Color.green, 0.25f ) );
|
assertEquals( new Color( 0x40bf00 ), ColorFunctions.mix( Color.red, Color.green, 0.25f ) );
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||||
<rect width="6" height="2" x="5" y="11.5" fill="#FFF"/>
|
<rect width="5" height="2" x="5.5" y="11.5" stroke="#FFF" stroke-linejoin="round"/>
|
||||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
<path stroke="#FFF" stroke-linejoin="round" d="M2.5,7.5 L8,2 L13.5,7.5 L10.5,7.5 L10.5,9.5 L5.5,9.5 L5.5,7.5 L2.5,7.5 Z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 408 B |
@@ -1,10 +1,12 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="2" height="2" x="2" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="7" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="11" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="7" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="11" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 682 B |
@@ -1,3 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="2 8 8 2 14 8 12 8 12 13 9 13 9 10 7 10 7 13 4 13 4 8"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linejoin="round" points="6.5 13 6.5 9.5 9.5 9.5 9.5 13"/>
|
||||||
|
<path stroke="#6E6E6E" d="M3.5,6.5 L3.5,12.5 C3.5,13.0522847 3.94771525,13.5 4.5,13.5 L11.5,13.5 C12.0522847,13.5 12.5,13.0522847 12.5,12.5 L12.5,6.5 L12.5,6.5"/>
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round" points="1.5 8.5 8 2 14.5 8.5"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 509 B |
@@ -1,8 +1,8 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="4" height="4" x="3" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="3" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 436 B |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 14 5 14 8 11 8 11 10 9 10 9 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#59A869" d="M14,11 L16,11 L16,13 L14,13 L14,15 L12,15 L12,13 L10,13 L10,11 L12,11 L12,9 L14,9 L14,11 Z"/>
|
<line x1="5.5" x2="10.5" y1="9" y2="9" stroke="#59A869" stroke-linecap="round"/>
|
||||||
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#59A869" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 632 B |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 9 5 9 9 13 9 13 5 14 5 14 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#389FD6" d="M12,4 L12,8 L10,8 L10,4 L8,4 L11,1 L14,4 L12,4 Z"/>
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#389FD6" stroke-linecap="round"/>
|
||||||
|
<polyline stroke="#389FD6" stroke-linecap="round" stroke-linejoin="round" points="5.5 9 8 6.5 10.5 9"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 303 B After Width: | Height: | Size: 655 B |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<path fill="#6E6E6E" d="M2,3 L14,3 L14,11 L2,11 L2,3 Z M4,5 L4,9 L12,9 L12,5 L4,5 Z"/>
|
<rect width="11" height="7" x="2.5" y="3.5" stroke="#6E6E6E" rx="1"/>
|
||||||
<rect width="12" height="2" x="2" y="12" fill="#6E6E6E"/>
|
<line x1="8" x2="8" y1="11" y2="12" stroke="#6E6E6E"/>
|
||||||
|
<line x1="4.5" x2="11.5" y1="12.5" y2="12.5" stroke="#6E6E6E" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 360 B |
@@ -1,3 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 176 B After Width: | Height: | Size: 427 B |
@@ -1,6 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<path stroke="#6E6E6E" d="M4,1.5 L8.8,1.5 L8.8,1.5 L13.5,6.2 L13.5,13 C13.5,13.8284271 12.8284271,14.5 12,14.5 L4,14.5 C3.17157288,14.5 2.5,13.8284271 2.5,13 L2.5,3 C2.5,2.17157288 3.17157288,1.5 4,1.5 Z"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<path stroke="#6E6E6E" d="M8.5,2 L8.5,5 C8.5,5.82842712 9.17157288,6.5 10,6.5 L13,6.5 L13,6.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 254 B After Width: | Height: | Size: 472 B |
@@ -1,6 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<path fill="#6E6E6E" d="M11,14 L11,11 L5,11 L5,14 L2,14 L2,2 L14,2 L14,14 L11,14 Z M4,4 L4,8 L12,8 L12,4 L4,4 Z"/>
|
<path stroke="#6E6E6E" d="M3.5,2.5 L11.5,2.5 L11.5,2.5 L13.5,4.5 L13.5,12.5 C13.5,13.0522847 13.0522847,13.5 12.5,13.5 L3.5,13.5 C2.94771525,13.5 2.5,13.0522847 2.5,12.5 L2.5,3.5 C2.5,2.94771525 2.94771525,2.5 3.5,2.5 Z"/>
|
||||||
<rect width="4" height="2" x="6" y="12" fill="#6E6E6E"/>
|
<polyline stroke="#6E6E6E" points="4.5 13 4.5 9.5 11.5 9.5 11.5 13"/>
|
||||||
|
<polyline stroke="#6E6E6E" points="5.5 3 5.5 5.5 10.5 5.5 10.5 3"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 533 B |
@@ -1,3 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<path fill="#6E6E6E" fill-rule="evenodd" d="M2,6 L14,6 L14,10 L2,10 L2,6 Z M12,8 L12,9 L13,9 L13,8 L12,8 Z M10,8 L10,9 L11,9 L11,8 L10,8 Z"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<rect width="11" height="5" x="2.5" y="5.5" stroke="#6E6E6E" rx="1"/>
|
||||||
|
<circle cx="11.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
<circle cx="9.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 317 B |