mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
138 Commits
fonts/robo
...
3.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d2f37e1da | ||
|
|
0494c2161c | ||
|
|
635a620439 | ||
|
|
0a7c76ec72 | ||
|
|
9ad8fb38e8 | ||
|
|
1dbe968952 | ||
|
|
460b6492cb | ||
|
|
67b0faa9ae | ||
|
|
5553425a1a | ||
|
|
8ff516e43a | ||
|
|
b6207bafde | ||
|
|
b9f43fd560 | ||
|
|
c617d9f569 | ||
|
|
9efb9761c6 | ||
|
|
03f9115fbf | ||
|
|
a2859cedb5 | ||
|
|
cdee0594f8 | ||
|
|
808833d749 | ||
|
|
581c64b601 | ||
|
|
c953ff84d0 | ||
|
|
96cd207df3 | ||
|
|
7a75f62a6a | ||
|
|
61e5fe58c2 | ||
|
|
1a3baba702 | ||
|
|
58dc14bb46 | ||
|
|
a5b7e04943 | ||
|
|
22f2aa5475 | ||
|
|
d4e9cb12be | ||
|
|
75da361480 | ||
|
|
7488bcb7b0 | ||
|
|
1b1a9be107 | ||
|
|
db2f94aa53 | ||
|
|
810146b993 | ||
|
|
93091662ab | ||
|
|
d349227fbf | ||
|
|
c9423e3aa8 | ||
|
|
b9737ca4f1 | ||
|
|
4b4990635d | ||
|
|
afaa2c8c78 | ||
|
|
f506ef0d4f | ||
|
|
d30fe66cac | ||
|
|
270e998e86 | ||
|
|
c395386c05 | ||
|
|
4f1207b0db | ||
|
|
dc3878e290 | ||
|
|
be2876149d | ||
|
|
52bae9dfb0 | ||
|
|
bb636bac3f | ||
|
|
502b18fa86 | ||
|
|
e0a5450264 | ||
|
|
5ffb23c37f | ||
|
|
b75f22b7bd | ||
|
|
35fa3197c8 | ||
|
|
f03725ae36 | ||
|
|
2b640e2129 | ||
|
|
2a983f5c03 | ||
|
|
cacc5daa14 | ||
|
|
593502287d | ||
|
|
7a9bdf9be0 | ||
|
|
170c22c5ed | ||
|
|
7e8fa58bd7 | ||
|
|
046200625c | ||
|
|
710ed55152 | ||
|
|
ce527329a6 | ||
|
|
b455dd41ab | ||
|
|
b47ed94f40 | ||
|
|
f1351a2093 | ||
|
|
c1c5e81df0 | ||
|
|
8e3c8ba6c5 | ||
|
|
dfe4404a17 | ||
|
|
b3fb63c9f5 | ||
|
|
9db3dfff26 | ||
|
|
3c9051e7de | ||
|
|
798a6d061c | ||
|
|
19afbe99d9 | ||
|
|
4715d8d16c | ||
|
|
193da2bc4d | ||
|
|
799f8efe22 | ||
|
|
f6062e1ec4 | ||
|
|
c790778a46 | ||
|
|
4344f1b3a0 | ||
|
|
d520b30500 | ||
|
|
11c02e5f50 | ||
|
|
aa4c6ee9da | ||
|
|
98f8557392 | ||
|
|
6f6a860887 | ||
|
|
38695e9e16 | ||
|
|
242c478cb3 | ||
|
|
f003e835bd | ||
|
|
267defb321 | ||
|
|
4392c7627b | ||
|
|
fde65b2730 | ||
|
|
e908362f0a | ||
|
|
a40b837634 | ||
|
|
b391465fbf | ||
|
|
bad0428f5b | ||
|
|
97018df2f9 | ||
|
|
9d84501bc8 | ||
|
|
e9fb2b3fdc | ||
|
|
f60250fd8a | ||
|
|
5fc3cae28a | ||
|
|
e7935be85b | ||
|
|
89363b2ea1 | ||
|
|
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 |
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
|||||||
toolchain: [""]
|
toolchain: [""]
|
||||||
include:
|
include:
|
||||||
- java: 17
|
- java: 17
|
||||||
toolchain: 19 # latest
|
toolchain: 21 # latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -39,9 +39,13 @@ jobs:
|
|||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
distribution: adopt # Java 8 and 11 are pre-installed on ubuntu-latest
|
distribution: temurin # Java 8, 11 and 17 are pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
|
- name: Check with Error Prone
|
||||||
|
if: matrix.java == '11'
|
||||||
|
run: ./gradlew errorprone clean -Dtoolchain=${{ matrix.toolchain }}
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
||||||
|
|
||||||
@@ -72,11 +76,11 @@ jobs:
|
|||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: adopt # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- name: Publish snapshot to oss.sonatype.org
|
||||||
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true
|
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
@@ -108,11 +112,11 @@ jobs:
|
|||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: adopt # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease
|
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||||
|
|||||||
2
.github/workflows/fonts.yml
vendored
2
.github/workflows/fonts.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
|||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: adopt # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
|
|||||||
2
.github/workflows/natives.yml
vendored
2
.github/workflows/natives.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: adopt
|
distribution: temurin
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
|
|||||||
169
CHANGELOG.md
169
CHANGELOG.md
@@ -1,12 +1,159 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
## 3.1-SNAPSHOT
|
## 3.2.2
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- Button: Fixed painting icon and text at wrong location when using HTML text,
|
||||||
|
left/right vertical alignment and running in Java 19+. (issue #746)
|
||||||
|
- CheckBox and RadioButton: Fixed cut off right side when border is removed and
|
||||||
|
horizontal alignment is set to `right`. (issue #734)
|
||||||
|
- TabbedPane: Fixed NPE when using focusable component as tab component and
|
||||||
|
switching theme. (issue #745)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.2.1
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- Fixed memory leak in
|
||||||
|
`MultiResolutionImageSupport.create(int,Dimension[],Function<Dimension,Image>)`,
|
||||||
|
which caches images created by the producer function. Used by
|
||||||
|
`FlatSVGIcon.getImage()` and `FlatSVGUtils.createWindowIconImages()`. If you
|
||||||
|
use one of these methods, it is **strongly recommended** to upgrade to this
|
||||||
|
version, because if the returned image is larger and painted very often it may
|
||||||
|
result in an out-of-memory situation. (issue #726)
|
||||||
|
- FileChooser: Fixed occasional NPE in `FlatShortcutsPanel` on Windows. (issue
|
||||||
|
#718)
|
||||||
|
- TextField: Fixed placeholder text painting, which did not respect horizontal
|
||||||
|
alignment property of `JTextField`. (issue #721)
|
||||||
|
- Popup: Fixed drop shadow if popup overlaps a heavyweight component. (Windows
|
||||||
|
10 only; issue #626)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.2
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
|
|
||||||
- Fonts: Added **Roboto
|
- TabbedPane: Support rounded underline selection and rounded card tabs. (PR
|
||||||
Mono** (https://fonts.google.com/specimen/Roboto+Mono). (PR #639, issue #638)
|
#703)
|
||||||
|
- FlatLaf window decorations:
|
||||||
|
- Support for Windows on ARM 64-bit. (issue #443, PR #707)
|
||||||
|
- Support toolbox-style "small" window title bar. (issue #659, PR #702)
|
||||||
|
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||||
|
library (instead of svgSalamander) for rendering. JSVG provides improved SVG
|
||||||
|
rendering and uses less memory compared to svgSalamander. (PR #684)
|
||||||
|
- ComboBox: Improved location of selected item in popup if list is large and
|
||||||
|
scrollable.
|
||||||
|
- FileChooser: Show localized text for all locales supported by Java's Metal
|
||||||
|
look and feel. (issue #680)
|
||||||
|
- Added system property `flatlaf.useNativeLibrary` to allow disabling loading of
|
||||||
|
FlatLaf native library. (issue #674)
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Reduced memory footprint by releasing Json data and ignoring IntelliJ UI
|
||||||
|
properties that are not used in FlatLaf.
|
||||||
|
- Updated "Hiberbee Dark" and "Gradianto" themes.
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- Styling: Fixed scaling of some styling properties (`rowHeight` for Table and
|
||||||
|
Tree; `iconTextGap` for Button, CheckBox and RadioButton). (issue #682)
|
||||||
|
- Fixed `IllegalComponentStateException` when invoker is not showing in
|
||||||
|
`SubMenuUsabilityHelper`. (issue #692)
|
||||||
|
- macOS themes: Changing `@accentColor` variable in FlatLaf properties files did
|
||||||
|
not change all accent related colors for all components.
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- "Light Owl" theme: Fixed wrong (unreadable) text color in selected menu
|
||||||
|
items, selected text in text components, and selection in ComboBox popup
|
||||||
|
list. (issue #687)
|
||||||
|
- "Gradianto Midnight Blue" theme: Fixed color of ScrollBar track, which was
|
||||||
|
not visible. (issue #686)
|
||||||
|
- "Monocai" theme: Fixed unreadable text color of default buttons. (issue
|
||||||
|
#693)
|
||||||
|
- "Vuesion" theme: Fixed foreground colors of disabled text.
|
||||||
|
- "Material UI Lite" themes: Fixed non-editable ComboBox button background.
|
||||||
|
- CheckBox and RadioButton: Fixed unselected icon colors for themes "Atom One
|
||||||
|
Light", "Cyan Light", "GitHub", "Light Owl", "Material Lighter" and
|
||||||
|
"Solarized Light".
|
||||||
|
- TabbedPane: Fixed focused tab background color for themes "Arc *", "Material
|
||||||
|
Design Dark", "Monocai", "One Dark", "Spacegray" and "Xcode-Dark". (issue
|
||||||
|
#697)
|
||||||
|
- TextComponents, ComboBox and Spinner: Fixed background colors of enabled
|
||||||
|
text components, to distinguish from disabled, for themes "Carbon", "Cobalt
|
||||||
|
2", "Gradianto *", "Gruvbox *", "Monocai", "Spacegray", "Vuesion",
|
||||||
|
"Xcode-Dark", "GitHub", and "Light Owl". (issue #528)
|
||||||
|
- Fixed wrong disabled text colors in "Dark Flat", "Hiberbee Dark", "Light
|
||||||
|
Flat", "Nord", "Solarized Dark" and "Solarized Light" themes.
|
||||||
|
- Fixed colors for selection background/foreground, Separator, Slider track
|
||||||
|
and ProgressBar background in various themes.
|
||||||
|
- Native Windows libraries: Fixed crash when running in Java 8 and newer Java
|
||||||
|
version is installed in `PATH` environment variable and using class
|
||||||
|
`SystemInfo` before AWT initialization. (issue #673)
|
||||||
|
- ComboBox: Fixed search in item list for text with spaces. (issue #691)
|
||||||
|
- FormattedTextField: On Linux, fixed `IllegalArgumentException: Invalid
|
||||||
|
location` if `JFormattedTextField.setDocument()` is invoked in a focus gained
|
||||||
|
listener on that formatted text field. (issue #698)
|
||||||
|
- PopupMenu: Make sure that popup menu does not overlap any operating system
|
||||||
|
task bar. (issue #701)
|
||||||
|
- FileChooser: Use system icons on Windows with Java 17.0.3 (and later) 32-bit.
|
||||||
|
Only Java 17 - 17.0.2 32-bit do not use system icons because of a bug in Java
|
||||||
|
32-bit that crashes the application. (PR #709)
|
||||||
|
- FileChooser: Fixed crash on Windows with Java 17 to 17.0.2 32-bit. Java 17
|
||||||
|
64-bit is not affected. (regression since FlatLaf 2.3; PR #522, see also issue
|
||||||
|
#403)
|
||||||
|
|
||||||
|
#### Incompatibilities
|
||||||
|
|
||||||
|
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||||
|
library for SVG rendering. You need to replace svgSalamander with JSVG in your
|
||||||
|
build scripts and distribute `jsvg.jar` with your application. Also replace
|
||||||
|
`com.kitfox.svg` with `com.github.weisj.jsvg` in `module-info.java` files.
|
||||||
|
- IntelliJ Themes: Removed all "Contrast" themes from "Material UI Lite".
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
#### Fixed bugs
|
||||||
|
|
||||||
@@ -15,11 +162,27 @@ FlatLaf Change Log
|
|||||||
decorations are used (e.g. Windows 10/11) or not (e.g. macOS). Now the glass
|
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)
|
pane no longer overlaps the FlatLaf window title bar. (issue #630)
|
||||||
- Linux: Fixed broken window resizing on multi-screen setups. (issue #632)
|
- 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:
|
- IntelliJ Themes:
|
||||||
- Fixed default button hover background in "Solarized Light" theme. (issue
|
- Fixed default button hover background in "Solarized Light" theme. (issue
|
||||||
#628)
|
#628)
|
||||||
- Avoid that accent color affect some colors in some IntelliJ themes. (issue
|
- Avoid that accent color affect some colors in some IntelliJ themes. (issue
|
||||||
#625)
|
#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
|
## 3.0
|
||||||
|
|||||||
278
README.md
278
README.md
@@ -6,7 +6,7 @@ Swing desktop applications.
|
|||||||
|
|
||||||
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
||||||
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
|
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
|
||||||
scales on **HiDPI** displays and runs on Java 8 or newer.
|
scales on **HiDPI** displays and runs on Java 8 or newer (LTS and latest).
|
||||||
|
|
||||||
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
||||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||||
@@ -66,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
|
||||||
|
|
||||||
@@ -137,6 +142,7 @@ Buzz
|
|||||||
----
|
----
|
||||||
|
|
||||||
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
||||||
|
- [FlatLaf 3.1 (and 3.0) announcement on Reddit](https://www.reddit.com/r/java/comments/12xgrsu/flatlaf_31_and_30_swing_look_and_feel/)
|
||||||
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
||||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||||
|
|
||||||
@@ -144,121 +150,193 @@ Buzz
|
|||||||
Applications using FlatLaf
|
Applications using FlatLaf
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
- 
|
### Featured
|
||||||
|
|
||||||
|
-  [JFormDesigner](https://www.formdev.com/)
|
||||||
|
(**commercial**) - Java/Swing GUI Designer (from the FlatLaf creators)
|
||||||
|
- 
|
||||||
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||||
12 (**commercial**) - the award-winning all-in-one Java profiler
|
(**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
|
|
||||||
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
|
||||||
OSHI, to view information about the system and hardware
|
|
||||||
- [Jailer](https://github.com/Wisser/Jailer) 11.2 - database subsetting and
|
|
||||||
relational data browsing tool
|
|
||||||
-  [Apache NetBeans](https://netbeans.apache.org/) 11.3 -
|
|
||||||
IDE for Java, PHP, HTML and much more
|
|
||||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
|
||||||
- [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
|
(**commercial**) - the powerful multi-platform Java installer builder
|
||||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
-  [DbVisualizer](https://www.dbvis.com/)
|
||||||
(**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
|
-  [Apache NetBeans](https://netbeans.apache.org/) - IDE
|
||||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
for Java, PHP, HTML and much more
|
||||||
- 
|
- 
|
||||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) (**commercial**) -
|
||||||
(**commercial**) - Thermodynamics and Properties Software
|
Thermodynamics and Properties Software
|
||||||
-  [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds
|
|
||||||
most widely used web app scanner
|
### Data
|
||||||
|
|
||||||
|
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||||
|
visual query system for relational databases
|
||||||
|
- [Jailer](https://github.com/Wisser/Jailer) - database subsetting and
|
||||||
|
relational data browsing tool
|
||||||
|
-  [MagicPlot](https://magicplot.com/) (**commercial**) -
|
||||||
|
Software for nonlinear fitting, plotting and data analysis
|
||||||
|
-  [Constellation](https://www.constellation-app.com/) -
|
||||||
|
Data Visualization and Analytics (based on NetBeans platform)
|
||||||
|
- 
|
||||||
|
[Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
|
||||||
|
client
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
-  [ZAP](https://www.zaproxy.org/) - the world's 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
|
(**commercial**) - the leading software for web security testing
|
||||||
|
- 
|
||||||
|
[Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
||||||
|
reverse engineering (SRE) framework
|
||||||
|
-  [jadx](https://github.com/skylot/jadx) - Dex to Java
|
||||||
|
decompiler
|
||||||
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||||
FlatLaf themes to Burp Suite
|
FlatLaf themes to Burp Suite
|
||||||
|
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
||||||
|
your website
|
||||||
|
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||||
|
encryption
|
||||||
|
|
||||||
|
### Software Development
|
||||||
|
|
||||||
|
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
||||||
|
- [KeyStore Explorer](https://keystore-explorer.org/)
|
||||||
|
- 
|
||||||
|
[muCommander](https://github.com/mucommander/mucommander) - lightweight
|
||||||
|
cross-platform file manager
|
||||||
|
-  [Guiffy](https://www.guiffy.com/) (**commercial**) -
|
||||||
|
advanced cross-platform Diff/Merge
|
||||||
|
-  [HashGarten](https://github.com/jonelo/HashGarten) -
|
||||||
|
cross-platform Swing GUI for Jacksum
|
||||||
|
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||||
|
IDE for Pseudo-Assembler
|
||||||
|
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
||||||
|
language created to learn programming
|
||||||
|
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
||||||
|
systems development platform
|
||||||
|
|
||||||
|
### Electrical
|
||||||
|
|
||||||
|
- [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) -
|
||||||
|
Digital logic design tool and simulator
|
||||||
|
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
|
||||||
|
for plotters, especially the wall-hanging polargraph
|
||||||
|
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
|
||||||
|
builder for [GUIslice](https://github.com/ImpulseAdventure/GUIslice), a
|
||||||
|
lightweight GUI framework for embedded displays
|
||||||
|
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
||||||
|
Arduino-based telescope focuser
|
||||||
|
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
||||||
|
control software
|
||||||
|
|
||||||
|
### Media
|
||||||
|
|
||||||
|
-  [jAlbum](https://jalbum.net/) (**commercial**) -
|
||||||
|
creates photo album websites
|
||||||
|
-  [MediathekView](https://mediathekview.de/) - search in
|
||||||
|
media libraries of various German broadcasters
|
||||||
|
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
|
||||||
|
sequences
|
||||||
|
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
|
||||||
|
media management tool
|
||||||
|
- [Weasis](https://nroduit.github.io/) - medical DICOM viewer used in healthcare
|
||||||
|
by hospitals, health networks, etc
|
||||||
|
- [Shutter Encoder](https://www.shutterencoder.com/)
|
||||||
|
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
||||||
|
professional video converter and compression tool
|
||||||
|
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
||||||
|
sound files in time or frequency domain
|
||||||
|
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
||||||
|
from any webnovel and lightnovel site
|
||||||
|
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
|
||||||
|
ease
|
||||||
|
|
||||||
|
### Modelling
|
||||||
|
|
||||||
|
-  [Astah](https://astah.net/) (**commercial**) - create
|
||||||
|
UML, ER Diagram, Flowchart, Data Flow Diagram, Requirement Diagram, SysML
|
||||||
|
diagrams and more
|
||||||
|
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||||
|
Application System
|
||||||
|
|
||||||
|
### Documents
|
||||||
|
|
||||||
|
-  [Big Faceless (BFO) PDF Viewer](https://bfo.com/)
|
||||||
|
(**commercial**) - Swing PDF Viewer
|
||||||
|
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
|
||||||
|
review and edit PDF documents
|
||||||
|
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
|
||||||
|
|
||||||
|
### Geo
|
||||||
|
|
||||||
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
||||||
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
||||||
JOSM plugin)
|
JOSM plugin)
|
||||||
-  [jAlbum](https://jalbum.net/) 21 (**commercial**) -
|
- [Mapton](https://mapton.org/)
|
||||||
creates photo album websites
|
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||||
- [PDF Studio](https://www.qoppa.com/pdfstudio/) 2021 (**commercial**) - create,
|
application (based on NetBeans platform)
|
||||||
review and edit PDF documents
|
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) - GIS and scientific
|
||||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
computation environment for meteorological community
|
||||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
|
||||||
checks your website
|
### Business / Legal
|
||||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
|
||||||
- [MegaMek](https://github.com/MegaMek/megamek),
|
- 
|
||||||
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5+ - a sci-fi tabletop
|
-  [Jeyla Studio](https://www.jeylastudio.com/) -
|
||||||
BattleTech simulator suite handling battles, unit building, and campaigns
|
Salon Software
|
||||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
- [Fanurio](https://www.fanuriotimetracking.com/) (**commercial**) - time
|
||||||
0.13.b024 - GUI builder for
|
tracking and billing for freelancers and teams
|
||||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
- [Jes](https://www.jes-eur.de) - Die Java-EÜR
|
||||||
framework for embedded displays
|
|
||||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
|
||||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
|
||||||
gamepad mapping software
|
|
||||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
|
||||||
connections manager
|
|
||||||
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
|
||||||
easy
|
|
||||||
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
||||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||||
[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) - Interactive Gravity and Magnetic
|
|
||||||
Application System
|
### Messaging
|
||||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
|
||||||
computation environment for meteorological community
|
-  [Spark](https://github.com/igniterealtime/Spark) -
|
||||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
cross-platform IM client optimized for businesses and organizations
|
||||||
systems development platform
|
-  [Chatty](https://github.com/chatty/chatty) - Twitch
|
||||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
Chat Client
|
||||||
encryption
|
|
||||||
- [Jes - Die Java-EÜR](https://www.jes-eur.de)
|
### Gaming
|
||||||
- [Mapton](https://mapton.org/) 2.0
|
|
||||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
-  
|
||||||
application (based on NetBeans platform)
|
[BGBlitz](https://www.bgblitz.com/) (**commercial**) - professional Backgammon
|
||||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
-  [MapTool](https://github.com/RPTools/maptool) - virtual
|
||||||
IDE for Pseudo-Assembler
|
Tabletop for playing role-playing games
|
||||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) 3.1 - French programming
|
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||||
language created to learn programming
|
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||||
- [MEKA](https://github.com/Waikato/meka) 1.9.3 - multi-label classifiers and
|
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
||||||
evaluation procedures using the Weka machine learning framework
|
simulator suite handling battles, unit building, and campaigns
|
||||||
- [Shutter Encoder](https://www.shutterencoder.com/) 14.2
|
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||||
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
gamepad mapping software
|
||||||
professional video converter and compression tool (screenshots show **old**
|
|
||||||
look)
|
### Utilities
|
||||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
|
||||||
sound files in time or frequency domain
|
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
OSHI, to view information about the system and hardware
|
||||||
control software
|
- 
|
||||||
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
[Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
||||||
Arduino-based telescope focuser
|
GUI for monitoring and managing various aspects of a Linux system
|
||||||
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||||
from any webnovel and lightnovel site
|
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||||
- [lectureStudio](https://www.lecturestudio.org/) 4.3.1060 - digitize your
|
connections manager
|
||||||
lectures with ease
|
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
||||||
|
easy
|
||||||
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
||||||
and fastboot commands easier to use
|
and fastboot commands easier to use
|
||||||
- and more...
|
|
||||||
|
### Miscellaneous
|
||||||
|
|
||||||
|
- [MEKA](https://github.com/Waikato/meka) - multi-label classifiers and
|
||||||
|
evaluation procedures using the Weka machine learning framework
|
||||||
|
|||||||
@@ -14,10 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val releaseVersion = "3.0"
|
import net.ltgt.gradle.errorprone.errorprone
|
||||||
val developmentVersion = "3.1-SNAPSHOT"
|
|
||||||
|
|
||||||
version = if( rootProject.hasProperty( "release" ) ) releaseVersion else developmentVersion
|
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
@@ -43,6 +42,10 @@ if( !toolchainJavaVersion.isNullOrEmpty() )
|
|||||||
println()
|
println()
|
||||||
|
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias( libs.plugins.errorprone ) apply false
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
tasks {
|
tasks {
|
||||||
withType<JavaCompile>().configureEach {
|
withType<JavaCompile>().configureEach {
|
||||||
@@ -81,4 +84,56 @@ allprojects {
|
|||||||
isFailOnError = false
|
isFailOnError = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---- Error Prone ----
|
||||||
|
|
||||||
|
tasks.register( "errorprone" ) {
|
||||||
|
group = "verification"
|
||||||
|
tasks.withType<JavaCompile>().forEach {
|
||||||
|
dependsOn( it )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val useErrorProne = gradle.startParameter.taskNames.contains( "errorprone" )
|
||||||
|
if( useErrorProne ) {
|
||||||
|
plugins.withType<JavaPlugin> {
|
||||||
|
apply( plugin = libs.plugins.errorprone.get().pluginId )
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
"errorprone"( libs.errorprone )
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
|
options.compilerArgs.add( "-Werror" )
|
||||||
|
options.errorprone {
|
||||||
|
disable(
|
||||||
|
"ReferenceEquality", // reports usage of '==' for objects
|
||||||
|
"StringSplitter", // reports String.split()
|
||||||
|
"JavaTimeDefaultTimeZone", // reports Year.now()
|
||||||
|
"MissingSummary", // reports `/** @since 2 */`
|
||||||
|
"InvalidBlockTag", // reports @uiDefault in javadoc
|
||||||
|
"AlreadyChecked", // reports false positives
|
||||||
|
"InlineMeSuggester", // suggests using Error Prone annotations for deprecated methods
|
||||||
|
"TypeParameterUnusedInFormals",
|
||||||
|
"UnsynchronizedOverridesSynchronized",
|
||||||
|
"NonApiType", // reports ArrayList/HashSet in parameter or return type
|
||||||
|
)
|
||||||
|
when( project.name ) {
|
||||||
|
"flatlaf-intellij-themes" -> disable(
|
||||||
|
"MutablePublicArray", // reports FlatAllIJThemes.INFOS
|
||||||
|
)
|
||||||
|
"flatlaf-theme-editor" -> disable(
|
||||||
|
"CatchAndPrintStackTrace",
|
||||||
|
)
|
||||||
|
"flatlaf-testing" -> disable(
|
||||||
|
"CatchAndPrintStackTrace",
|
||||||
|
"JdkObsolete", // reports Hashtable used for JSlider.setLabelTable()
|
||||||
|
"JavaUtilDate", // reports usage of class Date
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ tasks {
|
|||||||
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
||||||
dependsOn( ":flatlaf-core:compileJava" )
|
dependsOn( ":flatlaf-core:compileJava" )
|
||||||
|
|
||||||
from( project( ":flatlaf-core" ).buildDir.resolve( "generated/jni-headers" ) )
|
from( project( ":flatlaf-core" ).layout.buildDirectory.dir( "generated/jni-headers" ) )
|
||||||
into( "src/main/headers" )
|
into( "src/main/headers" )
|
||||||
include( extension.headers )
|
include( extension.headers )
|
||||||
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
||||||
|
|||||||
@@ -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
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,3 +122,11 @@ signing {
|
|||||||
tasks.withType<Sign>().configureEach {
|
tasks.withType<Sign>().configureEach {
|
||||||
onlyIf { rootProject.hasProperty( "release" ) }
|
onlyIf { rootProject.hasProperty( "release" ) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check whether parallel build is enabled
|
||||||
|
tasks.withType<PublishToMavenRepository>().configureEach {
|
||||||
|
doFirst {
|
||||||
|
if( System.getProperty( "org.gradle.parallel" ) == "true" )
|
||||||
|
throw RuntimeException( "Publishing does not work correctly with enabled parallel build. Disable parallel build with VM option '-Dorg.gradle.parallel=false'." )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=ISO-8859-1
|
||||||
@@ -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`
|
||||||
@@ -25,12 +27,11 @@ plugins {
|
|||||||
val sigtest = configurations.create( "sigtest" )
|
val sigtest = configurations.create( "sigtest" )
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
|
testImplementation( libs.bundles.junit )
|
||||||
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
|
testRuntimeOnly( libs.junit.engine )
|
||||||
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
|
|
||||||
|
|
||||||
// https://github.com/jtulach/netbeans-apitest
|
// https://github.com/jtulach/netbeans-apitest
|
||||||
sigtest( "org.netbeans.tools:sigtest-maven-plugin:1.7" )
|
sigtest( libs.sigtest )
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -41,7 +42,7 @@ java {
|
|||||||
tasks {
|
tasks {
|
||||||
compileJava {
|
compileJava {
|
||||||
// generate JNI headers
|
// generate JNI headers
|
||||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
options.headerOutputDirectory.set( layout.buildDirectory.dir( "generated/jni-headers" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
@@ -123,4 +124,12 @@ 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}/flatlaf-windows-arm64.dll", "windows-arm64", "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 3.0
|
#Version 3.2.2
|
||||||
|
|
||||||
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
|
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
|
||||||
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
|
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
|
||||||
@@ -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"
|
||||||
@@ -94,6 +96,8 @@ fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.title
|
|||||||
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"
|
||||||
|
fld public final static java.lang.String WINDOW_STYLE = "Window.style"
|
||||||
|
fld public final static java.lang.String WINDOW_STYLE_SMALL = "small"
|
||||||
meth public static <%0 extends java.lang.Object> {%%0} clientProperty(javax.swing.JComponent,java.lang.String,{%%0},java.lang.Class<{%%0}>)
|
meth public static <%0 extends java.lang.Object> {%%0} clientProperty(javax.swing.JComponent,java.lang.String,{%%0},java.lang.Class<{%%0}>)
|
||||||
meth public static boolean clientPropertyBoolean(javax.swing.JComponent,java.lang.String,boolean)
|
meth public static boolean clientPropertyBoolean(javax.swing.JComponent,java.lang.String,boolean)
|
||||||
meth public static boolean clientPropertyEquals(javax.swing.JComponent,java.lang.String,java.lang.Object)
|
meth public static boolean clientPropertyEquals(javax.swing.JComponent,java.lang.String,java.lang.Object)
|
||||||
@@ -278,6 +282,7 @@ fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.ui
|
|||||||
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
||||||
fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange"
|
fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange"
|
||||||
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
||||||
|
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
||||||
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
||||||
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
||||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"
|
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"
|
||||||
@@ -296,7 +301,7 @@ meth public static boolean setup(java.io.InputStream)
|
|||||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
|
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
|
||||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
|
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyInverseMapping,uiKeyMapping
|
hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludes,uiKeyInverseMapping,uiKeyMapping
|
||||||
|
|
||||||
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
|
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
|
||||||
outer com.formdev.flatlaf.IntelliJTheme
|
outer com.formdev.flatlaf.IntelliJTheme
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.IllegalComponentStateException;
|
||||||
|
import java.awt.Window;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
@@ -124,6 +126,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SQUARE_SIZE = "JButton.squareSize";
|
String SQUARE_SIZE = "JButton.squareSize";
|
||||||
|
|
||||||
|
|
||||||
//---- JComponent ---------------------------------------------------------
|
//---- JComponent ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,8 +269,28 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
||||||
|
|
||||||
|
|
||||||
//---- 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.
|
||||||
@@ -286,6 +309,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
||||||
|
|
||||||
|
|
||||||
//---- JProgressBar -------------------------------------------------------
|
//---- JProgressBar -------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -304,6 +328,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||||
|
|
||||||
|
|
||||||
//---- JRootPane ----------------------------------------------------------
|
//---- JRootPane ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -453,6 +478,37 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight";
|
String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style of the window title bar.
|
||||||
|
* Besides the default title bar style, you can use a Utility-style title bar,
|
||||||
|
* which is smaller than the default title bar.
|
||||||
|
* <p>
|
||||||
|
* On Windows 10/11, this requires FlatLaf window decorations.
|
||||||
|
* On macOS, Java supports this out of the box.
|
||||||
|
* <p>
|
||||||
|
* Note that this client property must be set before the window becomes displayable.
|
||||||
|
* Otherwise an {@link IllegalComponentStateException} is thrown.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #WINDOW_STYLE_SMALL}
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String WINDOW_STYLE = "Window.style";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window has Utility-style title bar, which is smaller than default title bar.
|
||||||
|
* <p>
|
||||||
|
* This is the same as using {@link Window#setType}( {@link Window.Type#UTILITY} ).
|
||||||
|
*
|
||||||
|
* @see #WINDOW_STYLE
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String WINDOW_STYLE_SMALL = "small";
|
||||||
|
|
||||||
|
|
||||||
//---- JScrollBar / JScrollPane -------------------------------------------
|
//---- JScrollBar / JScrollPane -------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -471,6 +527,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||||
|
|
||||||
|
|
||||||
//---- JSplitPane ---------------------------------------------------------
|
//---- JSplitPane ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -505,6 +562,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
||||||
|
|
||||||
|
|
||||||
//---- JTabbedPane --------------------------------------------------------
|
//---- JTabbedPane --------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -900,6 +958,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
||||||
|
|
||||||
|
|
||||||
//---- JTextField ---------------------------------------------------------
|
//---- JTextField ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1069,6 +1128,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
||||||
|
|
||||||
|
|
||||||
//---- JToggleButton ------------------------------------------------------
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1110,6 +1170,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||||
|
|
||||||
|
|
||||||
//---- JTree --------------------------------------------------------------
|
//---- JTree --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1129,6 +1190,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
||||||
|
|
||||||
|
|
||||||
//---- helper methods -----------------------------------------------------
|
//---- helper methods -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ class FlatInputMaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
||||||
"SPACE", "spacePopup",
|
// Space key still shows popup, but from FlatComboBoxUI.FlatKeySelectionManager
|
||||||
|
// "SPACE", "spacePopup",
|
||||||
|
|
||||||
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||||
"DOWN", mac( "selectNext2", "selectNext" ),
|
"DOWN", mac( "selectNext2", "selectNext" ),
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ import javax.swing.plaf.FontUIResource;
|
|||||||
import javax.swing.plaf.IconUIResource;
|
import javax.swing.plaf.IconUIResource;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicLookAndFeel;
|
import javax.swing.plaf.basic.BasicLookAndFeel;
|
||||||
|
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||||
import javax.swing.text.StyleContext;
|
import javax.swing.text.StyleContext;
|
||||||
import javax.swing.text.html.HTMLEditorKit;
|
import javax.swing.text.html.HTMLEditorKit;
|
||||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
||||||
@@ -391,7 +392,7 @@ public abstract class FlatLaf
|
|||||||
Method m = UIManager.class.getMethod( "createLookAndFeel", String.class );
|
Method m = UIManager.class.getMethod( "createLookAndFeel", String.class );
|
||||||
aquaLaf = (BasicLookAndFeel) m.invoke( null, "Mac OS X" );
|
aquaLaf = (BasicLookAndFeel) m.invoke( null, "Mac OS X" );
|
||||||
} else
|
} else
|
||||||
aquaLaf = (BasicLookAndFeel) Class.forName( aquaLafClassName ).getDeclaredConstructor().newInstance();
|
aquaLaf = Class.forName( aquaLafClassName ).asSubclass( BasicLookAndFeel.class ).getDeclaredConstructor().newInstance();
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to initialize Aqua look and feel '" + aquaLafClassName + "'.", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to initialize Aqua look and feel '" + aquaLafClassName + "'.", ex );
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
@@ -543,7 +544,7 @@ public abstract class FlatLaf
|
|||||||
// which can happen in applications that use some plugin system
|
// which can happen in applications that use some plugin system
|
||||||
// and load FlatLaf in a plugin that uses its own classloader.
|
// and load FlatLaf in a plugin that uses its own classloader.
|
||||||
// (e.g. Apache NetBeans)
|
// (e.g. Apache NetBeans)
|
||||||
if( defaults.get( "FileChooser.fileNameHeaderText" ) != null )
|
if( defaults.get( "TabbedPane.moreTabsButtonToolTipText" ) != null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// load FlatLaf resource bundle and add content to defaults
|
// load FlatLaf resource bundle and add content to defaults
|
||||||
@@ -581,10 +582,13 @@ public abstract class FlatLaf
|
|||||||
Object activeFont = new ActiveFont( null, null, -1, 0, 0, 0, 0 );
|
Object activeFont = new ActiveFont( null, null, -1, 0, 0, 0, 0 );
|
||||||
|
|
||||||
// override fonts
|
// override fonts
|
||||||
|
List<String> fontKeys = new ArrayList<>( 50 );
|
||||||
for( Object key : defaults.keySet() ) {
|
for( Object key : defaults.keySet() ) {
|
||||||
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
||||||
defaults.put( key, activeFont );
|
fontKeys.add( (String) key );
|
||||||
}
|
}
|
||||||
|
for( String key : fontKeys )
|
||||||
|
defaults.put( key, activeFont );
|
||||||
|
|
||||||
// add fonts that are not set in BasicLookAndFeel
|
// add fonts that are not set in BasicLookAndFeel
|
||||||
defaults.put( "RootPane.font", activeFont );
|
defaults.put( "RootPane.font", activeFont );
|
||||||
@@ -1428,26 +1432,36 @@ public abstract class FlatLaf
|
|||||||
private class FlatUIDefaults
|
private class FlatUIDefaults
|
||||||
extends UIDefaults
|
extends UIDefaults
|
||||||
{
|
{
|
||||||
|
private UIDefaults metalDefaults;
|
||||||
|
|
||||||
FlatUIDefaults( int initialCapacity, float loadFactor ) {
|
FlatUIDefaults( int initialCapacity, float loadFactor ) {
|
||||||
super( initialCapacity, loadFactor );
|
super( initialCapacity, loadFactor );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get( Object key ) {
|
public Object get( Object key ) {
|
||||||
Object value = getValue( key );
|
return get( key, null );
|
||||||
return (value != null) ? (value != NULL_VALUE ? value : null) : super.get( key );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get( Object key, Locale l ) {
|
public Object get( Object key, Locale l ) {
|
||||||
Object value = getValue( key );
|
Object value = getFromUIDefaultsGetters( key );
|
||||||
return (value != null) ? (value != NULL_VALUE ? value : null) : super.get( key, l );
|
if( value != null )
|
||||||
|
return (value != NULL_VALUE) ? value : null;
|
||||||
|
|
||||||
|
value = super.get( key, l );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
|
||||||
|
// get file chooser texts from Metal
|
||||||
|
return (key instanceof String && ((String)key).startsWith( "FileChooser." ))
|
||||||
|
? getFromMetal( (String) key, l )
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getValue( Object key ) {
|
private Object getFromUIDefaultsGetters( Object key ) {
|
||||||
// use local variable for getters to avoid potential multi-threading issues
|
// use local variable for getters to avoid potential multi-threading issues
|
||||||
List<Function<Object, Object>> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters;
|
List<Function<Object, Object>> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters;
|
||||||
|
|
||||||
if( uiDefaultsGetters == null )
|
if( uiDefaultsGetters == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1459,6 +1473,22 @@ public abstract class FlatLaf
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized Object getFromMetal( String key, Locale l ) {
|
||||||
|
if( metalDefaults == null ) {
|
||||||
|
metalDefaults = new MetalLookAndFeel() {
|
||||||
|
// avoid unnecessary initialization
|
||||||
|
@Override protected void initClassDefaults( UIDefaults table ) {}
|
||||||
|
@Override protected void initSystemColorDefaults( UIDefaults table ) {}
|
||||||
|
}.getDefaults();
|
||||||
|
|
||||||
|
// empty not needed defaults (to save memory) because we're only interested
|
||||||
|
// in resource bundle strings, which are stored in another internal map
|
||||||
|
metalDefaults.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return metalDefaults.get( key, l );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class ActiveFont ---------------------------------------------------
|
//---- class ActiveFont ---------------------------------------------------
|
||||||
@@ -1541,7 +1571,7 @@ public abstract class FlatLaf
|
|||||||
int newStyle = (style != -1)
|
int newStyle = (style != -1)
|
||||||
? style
|
? style
|
||||||
: (styleChange != 0)
|
: (styleChange != 0)
|
||||||
? baseStyle & ~((styleChange >> 16) & 0xffff) | (styleChange & 0xffff)
|
? (baseStyle & ~((styleChange >> 16) & 0xffff)) | (styleChange & 0xffff)
|
||||||
: baseStyle;
|
: baseStyle;
|
||||||
|
|
||||||
// new size
|
// new size
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,7 +97,7 @@ public class FlatPropertiesLaf
|
|||||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||||
lafClasses.add( FlatLaf.class );
|
lafClasses.add( FlatLaf.class );
|
||||||
switch( baseTheme.toLowerCase() ) {
|
switch( baseTheme.toLowerCase( Locale.ENGLISH ) ) {
|
||||||
default:
|
default:
|
||||||
case "light":
|
case "light":
|
||||||
lafClasses.add( FlatLightLaf.class );
|
lafClasses.add( FlatLightLaf.class );
|
||||||
|
|||||||
@@ -150,10 +150,24 @@ public interface FlatSystemProperties
|
|||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> {@code true}
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
* @since 2.5
|
* @since 2.5
|
||||||
*/
|
*/
|
||||||
String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange";
|
String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether FlatLaf native library should be used.
|
||||||
|
* <p>
|
||||||
|
* Setting this to {@code false} disables loading native library,
|
||||||
|
* which also disables some features that depend on the native library.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a directory in which the native FlatLaf libraries have been extracted.
|
* Specifies a directory in which the native FlatLaf libraries have been extracted.
|
||||||
* The path can be absolute or relative to current application working directory.
|
* The path can be absolute or relative to current application working directory.
|
||||||
|
|||||||
@@ -23,13 +23,17 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import javax.swing.UIDefaults;
|
import javax.swing.UIDefaults;
|
||||||
import javax.swing.plaf.ColorUIResource;
|
import javax.swing.plaf.ColorUIResource;
|
||||||
import com.formdev.flatlaf.json.Json;
|
import com.formdev.flatlaf.json.Json;
|
||||||
@@ -61,9 +65,9 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
private final boolean isMaterialUILite;
|
private final boolean isMaterialUILite;
|
||||||
|
|
||||||
private final Map<String, String> colors;
|
private Map<String, String> colors;
|
||||||
private final Map<String, Object> ui;
|
private Map<String, Object> ui;
|
||||||
private final Map<String, Object> icons;
|
private Map<String, Object> icons;
|
||||||
|
|
||||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
||||||
|
|
||||||
@@ -196,8 +200,9 @@ public class IntelliJTheme
|
|||||||
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
||||||
|
|
||||||
// IDEA uses TextField.background for editable ComboBox and Spinner
|
// IDEA uses TextField.background for editable ComboBox and Spinner
|
||||||
defaults.put( "ComboBox.editableBackground", defaults.get( "TextField.background" ) );
|
Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" );
|
||||||
defaults.put( "Spinner.background", defaults.get( "TextField.background" ) );
|
defaults.put( "ComboBox.editableBackground", textFieldBackground );
|
||||||
|
defaults.put( "Spinner.background", textFieldBackground );
|
||||||
|
|
||||||
// Spinner arrow button always has same colors as ComboBox arrow button
|
// Spinner arrow button always has same colors as ComboBox arrow button
|
||||||
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
||||||
@@ -205,22 +210,41 @@ public class IntelliJTheme
|
|||||||
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
||||||
|
|
||||||
// some themes specify colors for TextField.background, but forget to specify it for other components
|
// some themes specify colors for TextField.background, but forget to specify it for other components
|
||||||
// (probably because those components are not used in IntelliJ)
|
// (probably because those components are not used in IntelliJ IDEA)
|
||||||
if( uiKeys.contains( "TextField.background" ) ) {
|
putAll( defaults, textFieldBackground,
|
||||||
Object textFieldBackground = defaults.get( "TextField.background" );
|
"EditorPane.background",
|
||||||
if( !uiKeys.contains( "FormattedTextField.background" ) )
|
"FormattedTextField.background",
|
||||||
defaults.put( "FormattedTextField.background", textFieldBackground );
|
"PasswordField.background",
|
||||||
if( !uiKeys.contains( "PasswordField.background" ) )
|
"TextArea.background",
|
||||||
defaults.put( "PasswordField.background", textFieldBackground );
|
"TextPane.background"
|
||||||
if( !uiKeys.contains( "EditorPane.background" ) )
|
);
|
||||||
defaults.put( "EditorPane.background", textFieldBackground );
|
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ),
|
||||||
if( !uiKeys.contains( "TextArea.background" ) )
|
"EditorPane.selectionBackground",
|
||||||
defaults.put( "TextArea.background", textFieldBackground );
|
"FormattedTextField.selectionBackground",
|
||||||
if( !uiKeys.contains( "TextPane.background" ) )
|
"PasswordField.selectionBackground",
|
||||||
defaults.put( "TextPane.background", textFieldBackground );
|
"TextArea.selectionBackground",
|
||||||
if( !uiKeys.contains( "Spinner.background" ) )
|
"TextPane.selectionBackground"
|
||||||
defaults.put( "Spinner.background", textFieldBackground );
|
);
|
||||||
}
|
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ),
|
||||||
|
"EditorPane.selectionForeground",
|
||||||
|
"FormattedTextField.selectionForeground",
|
||||||
|
"PasswordField.selectionForeground",
|
||||||
|
"TextArea.selectionForeground",
|
||||||
|
"TextPane.selectionForeground"
|
||||||
|
);
|
||||||
|
|
||||||
|
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
||||||
|
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
||||||
|
putAll( defaults, panelBackground,
|
||||||
|
"ComboBox.disabledBackground",
|
||||||
|
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
||||||
|
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
||||||
|
"PasswordField.disabledBackground", "PasswordField.inactiveBackground",
|
||||||
|
"Spinner.disabledBackground",
|
||||||
|
"TextArea.disabledBackground", "TextArea.inactiveBackground",
|
||||||
|
"TextField.disabledBackground", "TextField.inactiveBackground",
|
||||||
|
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
||||||
|
);
|
||||||
|
|
||||||
// fix ToggleButton
|
// fix ToggleButton
|
||||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
||||||
@@ -247,6 +271,33 @@ public class IntelliJTheme
|
|||||||
if( rowHeight > 22 )
|
if( rowHeight > 22 )
|
||||||
defaults.put( "Tree.rowHeight", 22 );
|
defaults.put( "Tree.rowHeight", 22 );
|
||||||
|
|
||||||
|
// get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix
|
||||||
|
HashMap<String, Object> wildcards = new HashMap<>();
|
||||||
|
Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
|
||||||
|
while( it.hasNext() ) {
|
||||||
|
Entry<Object, Object> e = it.next();
|
||||||
|
String key = (String) e.getKey();
|
||||||
|
if( key.startsWith( "*." ) ) {
|
||||||
|
wildcards.put( key.substring( "*.".length() ), e.getValue() );
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// override UI defaults with theme specific wildcard replacements
|
||||||
|
if( !wildcards.isEmpty() ) {
|
||||||
|
for( Object key : defaults.keySet().toArray() ) {
|
||||||
|
int dot;
|
||||||
|
if( !(key instanceof String) ||
|
||||||
|
(dot = ((String)key).lastIndexOf( '.' )) < 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String wildcardKey = ((String)key).substring( dot + 1 );
|
||||||
|
Object wildcardValue = wildcards.get( wildcardKey );
|
||||||
|
if( wildcardValue != null )
|
||||||
|
defaults.put( key, wildcardValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// apply theme specific UI defaults at the end to allow overwriting
|
// apply theme specific UI defaults at the end to allow overwriting
|
||||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||||
Object key = e.getKey();
|
Object key = e.getKey();
|
||||||
@@ -261,6 +312,20 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
defaults.put( key, value );
|
defaults.put( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let Java release memory
|
||||||
|
colors = null;
|
||||||
|
ui = null;
|
||||||
|
icons = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object get( UIDefaults defaults, Map<Object, Object> themeSpecificDefaults, String key ) {
|
||||||
|
return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putAll( UIDefaults defaults, Object value, String... keys ) {
|
||||||
|
for( String key : keys )
|
||||||
|
defaults.put( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||||
@@ -334,17 +399,30 @@ public class IntelliJTheme
|
|||||||
if( "".equals( value ) )
|
if( "".equals( value ) )
|
||||||
return; // ignore empty value
|
return; // ignore empty value
|
||||||
|
|
||||||
uiKeys.add( key );
|
// ignore some properties that affect sizes
|
||||||
|
if( key.endsWith( ".border" ) ||
|
||||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
key.endsWith( ".rowHeight" ) ||
|
||||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
key.equals( "ComboBox.padding" ) ||
|
||||||
return; // ignore
|
key.equals( "Spinner.padding" ) ||
|
||||||
|
key.equals( "Tree.leftChildIndent" ) ||
|
||||||
|
key.equals( "Tree.rightChildIndent" ) )
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
// map keys
|
// map keys
|
||||||
key = uiKeyMapping.getOrDefault( key, key );
|
key = uiKeyMapping.getOrDefault( key, key );
|
||||||
if( key.isEmpty() )
|
if( key.isEmpty() )
|
||||||
return; // ignore key
|
return; // ignore key
|
||||||
|
|
||||||
|
// exclude properties
|
||||||
|
int dot = key.indexOf( '.' );
|
||||||
|
if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
uiKeys.add( key );
|
||||||
|
|
||||||
String valueStr = value.toString();
|
String valueStr = value.toString();
|
||||||
|
|
||||||
// map named colors
|
// map named colors
|
||||||
@@ -390,7 +468,8 @@ public class IntelliJTheme
|
|||||||
// replace all values in UI defaults that match the wildcard key
|
// replace all values in UI defaults that match the wildcard key
|
||||||
for( Object k : defaultsKeysCache ) {
|
for( Object k : defaultsKeysCache ) {
|
||||||
if( k.equals( "Desktop.background" ) ||
|
if( k.equals( "Desktop.background" ) ||
|
||||||
k.equals( "DesktopIcon.background" ) )
|
k.equals( "DesktopIcon.background" ) ||
|
||||||
|
k.equals( "TabbedPane.focusColor" ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( k instanceof String ) {
|
if( k instanceof String ) {
|
||||||
@@ -461,7 +540,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
||||||
* this two components are specified in "icons > ColorPalette".
|
* these two components are specified in "icons > ColorPalette".
|
||||||
* FlatLaf uses vector icons and expects colors for the two components in UI defaults.
|
* FlatLaf uses vector icons and expects colors for the two components in UI defaults.
|
||||||
*/
|
*/
|
||||||
private void applyCheckBoxColors( UIDefaults defaults ) {
|
private void applyCheckBoxColors( UIDefaults defaults ) {
|
||||||
@@ -481,18 +560,6 @@ public class IntelliJTheme
|
|||||||
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( key.equals( "Checkbox.Background.Default" ) ||
|
|
||||||
key.equals( "Checkbox.Foreground.Selected" ) )
|
|
||||||
{
|
|
||||||
// This two keys do not work correctly in IDEA because they
|
|
||||||
// map SVG color "#ffffff" to another color, but checkBox.svg and
|
|
||||||
// radio.svg (in package com.intellij.ide.ui.laf.icons.intellij)
|
|
||||||
// use "#fff". So use white to get same appearance as in IDEA.
|
|
||||||
value = "#ffffff";
|
|
||||||
}
|
|
||||||
|
|
||||||
String key2 = checkboxDuplicateColors.get( key );
|
|
||||||
|
|
||||||
if( dark )
|
if( dark )
|
||||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||||
|
|
||||||
@@ -506,6 +573,7 @@ public class IntelliJTheme
|
|||||||
if( color != null ) {
|
if( color != null ) {
|
||||||
defaults.put( newKey, color );
|
defaults.put( newKey, color );
|
||||||
|
|
||||||
|
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
||||||
if( key2 != null ) {
|
if( key2 != null ) {
|
||||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
||||||
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||||
@@ -570,17 +638,59 @@ public class IntelliJTheme
|
|||||||
defaults.put( destKey, defaults.get( srcKey ) );
|
defaults.put( destKey, defaults.get( srcKey ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Set<String> uiKeyExcludes;
|
||||||
|
private static final Set<String> uiKeyDoNotOverride;
|
||||||
/** Rename UI default keys (key --> value). */
|
/** Rename UI default keys (key --> value). */
|
||||||
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||||
/** Copy UI default keys (value --> key). */
|
/** Copy UI default keys (value --> key). */
|
||||||
private static final Map<String, String> uiKeyCopying = new HashMap<>();
|
private static final Map<String, String> uiKeyCopying = new LinkedHashMap<>();
|
||||||
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||||
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||||
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
// IntelliJ UI properties that are not used in FlatLaf
|
||||||
|
uiKeyExcludes = new HashSet<>( Arrays.asList(
|
||||||
|
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||||
|
"AvailableMnemonic.",
|
||||||
|
"BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||||
|
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||||
|
"Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
|
||||||
|
"CurrentMnemonic.", "Counter.",
|
||||||
|
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
|
||||||
|
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
||||||
|
"FileColor.", "FlameGraph.", "Focus.",
|
||||||
|
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
||||||
|
"HeaderColor.", "HelpTooltip.", "Hg.",
|
||||||
|
"IconBadge.", "InformationHint.", "InplaceRefactoringPopup.",
|
||||||
|
"Lesson.", "Link.", "LiveIndicator.",
|
||||||
|
"MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||||
|
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||||
|
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||||
|
"ParameterInfo.", "Plugins.", "ProgressIcon.", "PsiViewer.",
|
||||||
|
"ReviewList.", "RunWidget.",
|
||||||
|
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
||||||
|
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
||||||
|
"StatusBar.",
|
||||||
|
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
|
||||||
|
"UIDesigner.", "UnattendedHostStatus.",
|
||||||
|
"ValidationTooltip.", "VersionControl.",
|
||||||
|
"WelcomeScreen.",
|
||||||
|
|
||||||
|
// lower case
|
||||||
|
"darcula.", "dropArea.", "icons.", "intellijlaf.", "macOSWindow.", "material.", "tooltips.",
|
||||||
|
|
||||||
|
// possible typos in .theme.json files
|
||||||
|
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
|
||||||
|
) );
|
||||||
|
|
||||||
|
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
||||||
|
"TabbedPane.selectedForeground"
|
||||||
|
) );
|
||||||
|
|
||||||
// ComboBox
|
// ComboBox
|
||||||
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
||||||
|
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
||||||
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||||
@@ -638,9 +748,9 @@ public class IntelliJTheme
|
|||||||
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||||
|
|
||||||
// TabbedPane
|
// TabbedPane
|
||||||
uiKeyCopying.put( "TabbedPane.selectedBackground", "DefaultTabs.underlinedTabBackground" );
|
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
|
||||||
uiKeyCopying.put( "TabbedPane.selectedForeground", "DefaultTabs.underlinedTabForeground" );
|
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
|
||||||
uiKeyCopying.put( "TabbedPane.inactiveUnderlineColor", "DefaultTabs.inactiveUnderlineColor" );
|
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
|
||||||
|
|
||||||
// TitlePane
|
// TitlePane
|
||||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
||||||
|
|||||||
@@ -23,11 +23,14 @@ import java.awt.GraphicsEnvironment;
|
|||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import javax.swing.text.StyleContext;
|
import javax.swing.text.StyleContext;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
@@ -68,7 +71,7 @@ class LinuxFontPolicy
|
|||||||
if( word.endsWith( "," ) )
|
if( word.endsWith( "," ) )
|
||||||
word = word.substring( 0, word.length() - 1 ).trim();
|
word = word.substring( 0, word.length() - 1 ).trim();
|
||||||
|
|
||||||
String lword = word.toLowerCase();
|
String lword = word.toLowerCase( Locale.ENGLISH );
|
||||||
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
||||||
style |= Font.ITALIC;
|
style |= Font.ITALIC;
|
||||||
else if( lword.equals( "bold" ) )
|
else if( lword.equals( "bold" ) )
|
||||||
@@ -104,7 +107,7 @@ class LinuxFontPolicy
|
|||||||
size = 1;
|
size = 1;
|
||||||
|
|
||||||
// handle logical font names
|
// handle logical font names
|
||||||
String logicalFamily = mapFcName( family.toLowerCase() );
|
String logicalFamily = mapFcName( family.toLowerCase( Locale.ENGLISH ) );
|
||||||
if( logicalFamily != null )
|
if( logicalFamily != null )
|
||||||
family = logicalFamily;
|
family = logicalFamily;
|
||||||
|
|
||||||
@@ -143,7 +146,7 @@ class LinuxFontPolicy
|
|||||||
return createFont( Font.DIALOG, style, size, dsize );
|
return createFont( Font.DIALOG, style, size, dsize );
|
||||||
|
|
||||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||||
String lastWord = family.substring( index + 1 ).toLowerCase();
|
String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH );
|
||||||
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
||||||
style |= Font.BOLD;
|
style |= Font.BOLD;
|
||||||
|
|
||||||
@@ -257,6 +260,7 @@ class LinuxFontPolicy
|
|||||||
return createFont( family, style, size, dsize );
|
return createFont( family, style, size, dsize );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone
|
||||||
private static List<String> readConfig( String filename ) {
|
private static List<String> readConfig( String filename ) {
|
||||||
File userHome = new File( System.getProperty( "user.home" ) );
|
File userHome = new File( System.getProperty( "user.home" ) );
|
||||||
|
|
||||||
@@ -277,7 +281,9 @@ class LinuxFontPolicy
|
|||||||
|
|
||||||
// read config file
|
// read config file
|
||||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
try( BufferedReader reader = new BufferedReader( new InputStreamReader(
|
||||||
|
new FileInputStream( file ), StandardCharsets.US_ASCII ) ) )
|
||||||
|
{
|
||||||
String line;
|
String line;
|
||||||
while( (line = reader.readLine()) != null )
|
while( (line = reader.readLine()) != null )
|
||||||
lines.add( line );
|
lines.add( line );
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ debug*/
|
|||||||
|
|
||||||
// get invoker screen bounds
|
// get invoker screen bounds
|
||||||
Component invoker = popup.getInvoker();
|
Component invoker = popup.getInvoker();
|
||||||
invokerBounds = (invoker != null)
|
invokerBounds = (invoker != null && invoker.isShowing())
|
||||||
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,12 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StreamTokenizer;
|
import java.io.StreamTokenizer;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -271,8 +275,9 @@ class UIDefaultsLoader
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String value = resolveValue( (String) e.getValue(), propertiesGetter );
|
String value = (String) e.getValue();
|
||||||
try {
|
try {
|
||||||
|
value = resolveValue( value, propertiesGetter );
|
||||||
defaults.put( key, parseValue( key, value, null, null, resolver, addonClassLoaders ) );
|
defaults.put( key, parseValue( key, value, null, null, resolver, addonClassLoaders ) );
|
||||||
} catch( RuntimeException ex ) {
|
} catch( RuntimeException ex ) {
|
||||||
logParseError( key, value, ex, true );
|
logParseError( key, value, ex, true );
|
||||||
@@ -297,7 +302,9 @@ class UIDefaultsLoader
|
|||||||
LoggingFacade.INSTANCE.logConfig( message, ex );
|
LoggingFacade.INSTANCE.logConfig( message, ex );
|
||||||
}
|
}
|
||||||
|
|
||||||
static String resolveValue( String value, Function<String, String> propertiesGetter ) {
|
static String resolveValue( String value, Function<String, String> propertiesGetter )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
String value0 = value;
|
String value0 = value;
|
||||||
|
|
||||||
@@ -326,7 +333,9 @@ class UIDefaultsLoader
|
|||||||
return resolveValue( newValue, propertiesGetter );
|
return resolveValue( newValue, propertiesGetter );
|
||||||
}
|
}
|
||||||
|
|
||||||
static String resolveValueFromUIManager( String value ) {
|
static String resolveValueFromUIManager( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( value.startsWith( VARIABLE_PREFIX ) ) {
|
if( value.startsWith( VARIABLE_PREFIX ) ) {
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
Map<String, String> variables = (Map<String, String>) UIManager.get( KEY_VARIABLES );
|
Map<String, String> variables = (Map<String, String>) UIManager.get( KEY_VARIABLES );
|
||||||
@@ -334,7 +343,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 ) )
|
||||||
@@ -348,8 +357,11 @@ class UIDefaultsLoader
|
|||||||
// convert binary color to string
|
// convert binary color to string
|
||||||
if( newValue instanceof Color ) {
|
if( newValue instanceof Color ) {
|
||||||
Color color = (Color) newValue;
|
Color color = (Color) newValue;
|
||||||
|
int rgb = color.getRGB() & 0xffffff;
|
||||||
int alpha = color.getAlpha();
|
int alpha = color.getAlpha();
|
||||||
return String.format( (alpha != 255) ? "#%06x%02x" : "#%06x", color.getRGB() & 0xffffff, alpha );
|
return (alpha != 255)
|
||||||
|
? String.format( "#%06x%02x", rgb, alpha )
|
||||||
|
: String.format( "#%06x", rgb );
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException( "property value type '" + newValue.getClass().getName() + "' not supported in references" );
|
throw new IllegalArgumentException( "property value type '" + newValue.getClass().getName() + "' not supported in references" );
|
||||||
@@ -362,12 +374,15 @@ class UIDefaultsLoader
|
|||||||
private static Map<Class<?>, ValueType> javaValueTypes;
|
private static Map<Class<?>, ValueType> javaValueTypes;
|
||||||
private static Map<String, ValueType> knownValueTypes;
|
private static Map<String, ValueType> knownValueTypes;
|
||||||
|
|
||||||
static Object parseValue( String key, String value, Class<?> valueType ) {
|
static Object parseValue( String key, String value, Class<?> valueType )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
return parseValue( key, value, valueType, null, v -> v, Collections.emptyList() );
|
return parseValue( key, value, valueType, null, v -> v, Collections.emptyList() );
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object parseValue( String key, String value, Class<?> javaValueType, ValueType[] resultValueType,
|
static Object parseValue( String key, String value, Class<?> javaValueType, ValueType[] resultValueType,
|
||||||
Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
if( resultValueType == null )
|
if( resultValueType == null )
|
||||||
resultValueType = tempResultValueType;
|
resultValueType = tempResultValueType;
|
||||||
@@ -397,7 +412,7 @@ class UIDefaultsLoader
|
|||||||
if( value.startsWith( "if(" ) && value.endsWith( ")" ) ) {
|
if( value.startsWith( "if(" ) && value.endsWith( ")" ) ) {
|
||||||
List<String> params = splitFunctionParams( value.substring( 3, value.length() - 1 ), ',' );
|
List<String> params = splitFunctionParams( value.substring( 3, value.length() - 1 ), ',' );
|
||||||
if( params.size() != 3 )
|
if( params.size() != 3 )
|
||||||
throwMissingParametersException( value );
|
throw newMissingParametersException( value );
|
||||||
|
|
||||||
boolean ifCondition = parseCondition( params.get( 0 ), resolver, addonClassLoaders );
|
boolean ifCondition = parseCondition( params.get( 0 ), resolver, addonClassLoaders );
|
||||||
String ifValue = params.get( ifCondition ? 1 : 2 );
|
String ifValue = params.get( ifCondition ? 1 : 2 );
|
||||||
@@ -537,7 +552,7 @@ class UIDefaultsLoader
|
|||||||
case INTEGERORFLOAT:return parseIntegerOrFloat( value );
|
case INTEGERORFLOAT:return parseIntegerOrFloat( value );
|
||||||
case FLOAT: return parseFloat( value );
|
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, resolver, 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 );
|
case COLOR: return parseColorOrFunction( value, resolver );
|
||||||
@@ -546,7 +561,7 @@ class UIDefaultsLoader
|
|||||||
case SCALEDFLOAT: return parseScaledFloat( value );
|
case SCALEDFLOAT: return parseScaledFloat( value );
|
||||||
case SCALEDINSETS: return parseScaledInsets( value );
|
case SCALEDINSETS: return parseScaledInsets( value );
|
||||||
case SCALEDDIMENSION:return parseScaledDimension( value );
|
case SCALEDDIMENSION:return parseScaledDimension( value );
|
||||||
case INSTANCE: return parseInstance( value, addonClassLoaders );
|
case INSTANCE: return parseInstance( value, resolver, addonClassLoaders );
|
||||||
case CLASS: return parseClass( value, addonClassLoaders );
|
case CLASS: return parseClass( value, addonClassLoaders );
|
||||||
case GRAYFILTER: return parseGrayFilter( value );
|
case GRAYFILTER: return parseGrayFilter( value );
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
@@ -608,9 +623,11 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( value.indexOf( ',' ) >= 0 ) {
|
if( value.indexOf( ',' ) >= 0 ) {
|
||||||
// top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
// Syntax: top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
||||||
List<String> parts = splitFunctionParams( value, ',' );
|
List<String> parts = splitFunctionParams( value, ',' );
|
||||||
Insets insets = parseInsets( value );
|
Insets insets = parseInsets( value );
|
||||||
ColorUIResource lineColor = (parts.size() >= 5)
|
ColorUIResource lineColor = (parts.size() >= 5)
|
||||||
@@ -625,13 +642,29 @@ class UIDefaultsLoader
|
|||||||
: new FlatEmptyBorder( insets );
|
: new FlatEmptyBorder( insets );
|
||||||
};
|
};
|
||||||
} else
|
} else
|
||||||
return parseInstance( value, addonClassLoaders );
|
return parseInstance( value, resolver, addonClassLoaders );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseInstance( String value, List<ClassLoader> addonClassLoaders ) {
|
private static Object parseInstance( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||||
return (LazyValue) t -> {
|
return (LazyValue) t -> {
|
||||||
try {
|
try {
|
||||||
return findClass( value, addonClassLoaders ).getDeclaredConstructor().newInstance();
|
if( value.indexOf( ',' ) >= 0 ) {
|
||||||
|
// Syntax: className,param1,param2,...
|
||||||
|
List<String> parts = splitFunctionParams( value, ',' );
|
||||||
|
String className = parts.get( 0 );
|
||||||
|
Class<?> cls = findClass( className, addonClassLoaders );
|
||||||
|
|
||||||
|
Constructor<?>[] constructors = cls.getDeclaredConstructors();
|
||||||
|
Object result = invokeConstructorOrStaticMethod( constructors, parts, resolver );
|
||||||
|
if( result != null )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to instantiate '" + className
|
||||||
|
+ "': no constructor found for parameters '"
|
||||||
|
+ value.substring( value.indexOf( ',' + 1 ) ) + "'.", null );
|
||||||
|
return null;
|
||||||
|
} else
|
||||||
|
return findClass( value, addonClassLoaders ).getDeclaredConstructor().newInstance();
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to instantiate '" + value + "'.", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to instantiate '" + value + "'.", ex );
|
||||||
return null;
|
return null;
|
||||||
@@ -668,7 +701,9 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Insets parseInsets( String value ) {
|
private static Insets parseInsets( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
List<String> numbers = StringUtils.split( value, ',', true, false );
|
List<String> numbers = StringUtils.split( value, ',', true, false );
|
||||||
try {
|
try {
|
||||||
return new InsetsUIResource(
|
return new InsetsUIResource(
|
||||||
@@ -681,7 +716,9 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dimension parseDimension( String value ) {
|
private static Dimension parseDimension( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
List<String> numbers = StringUtils.split( value, ',', true, false );
|
List<String> numbers = StringUtils.split( value, ',', true, false );
|
||||||
try {
|
try {
|
||||||
return new DimensionUIResource(
|
return new DimensionUIResource(
|
||||||
@@ -692,7 +729,9 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseColorOrFunction( String value, Function<String, String> resolver ) {
|
private static Object parseColorOrFunction( String value, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( value.endsWith( ")" ) )
|
if( value.endsWith( ")" ) )
|
||||||
return parseColorFunctions( value, resolver );
|
return parseColorFunctions( value, resolver );
|
||||||
|
|
||||||
@@ -702,10 +741,10 @@ class UIDefaultsLoader
|
|||||||
/**
|
/**
|
||||||
* Parses a hex color in {@code #RGB}, {@code #RGBA}, {@code #RRGGBB} or {@code #RRGGBBAA}
|
* Parses a hex color in {@code #RGB}, {@code #RGBA}, {@code #RRGGBB} or {@code #RRGGBBAA}
|
||||||
* format and returns it as color object.
|
* format and returns it as color object.
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
*/
|
*/
|
||||||
static ColorUIResource parseColor( String value ) {
|
static ColorUIResource parseColor( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
int rgba = parseColorRGBA( value );
|
int rgba = parseColorRGBA( value );
|
||||||
return ((rgba & 0xff000000) == 0xff000000)
|
return ((rgba & 0xff000000) == 0xff000000)
|
||||||
? new ColorUIResource( rgba )
|
? new ColorUIResource( rgba )
|
||||||
@@ -716,10 +755,10 @@ class UIDefaultsLoader
|
|||||||
* Parses a hex color in {@code #RGB}, {@code #RGBA}, {@code #RRGGBB} or {@code #RRGGBBAA}
|
* Parses a hex color in {@code #RGB}, {@code #RGBA}, {@code #RRGGBB} or {@code #RRGGBBAA}
|
||||||
* format and returns it as {@code rgba} integer suitable for {@link java.awt.Color},
|
* format and returns it as {@code rgba} integer suitable for {@link java.awt.Color},
|
||||||
* which includes alpha component in bits 24-31.
|
* which includes alpha component in bits 24-31.
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
*/
|
*/
|
||||||
static int parseColorRGBA( String value ) {
|
static int parseColorRGBA( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
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 newInvalidColorException( value );
|
throw newInvalidColorException( value );
|
||||||
@@ -760,7 +799,9 @@ class UIDefaultsLoader
|
|||||||
return new IllegalArgumentException( "invalid color '" + value + "'" );
|
return new IllegalArgumentException( "invalid color '" + value + "'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseColorFunctions( String value, Function<String, String> resolver ) {
|
private static Object parseColorFunctions( String value, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
int paramsStart = value.indexOf( '(' );
|
int paramsStart = value.indexOf( '(' );
|
||||||
if( paramsStart < 0 )
|
if( paramsStart < 0 )
|
||||||
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
|
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
|
||||||
@@ -768,7 +809,7 @@ class UIDefaultsLoader
|
|||||||
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() )
|
||||||
throwMissingParametersException( value );
|
throw newMissingParametersException( value );
|
||||||
|
|
||||||
if( parseColorDepth > 100 )
|
if( parseColorDepth > 100 )
|
||||||
throw new IllegalArgumentException( "endless recursion in color function '" + value + "'" );
|
throw new IllegalArgumentException( "endless recursion in color function '" + value + "'" );
|
||||||
@@ -813,9 +854,11 @@ 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 ) {
|
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( params.size() != 3 )
|
if( params.size() != 3 )
|
||||||
throwMissingParametersException( value );
|
throw newMissingParametersException( 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 );
|
||||||
@@ -827,9 +870,11 @@ class UIDefaultsLoader
|
|||||||
* - name: system color name
|
* - name: system color name
|
||||||
* - defaultValue: default color value used if system color is not available
|
* - defaultValue: default color value used if system color is not available
|
||||||
*/
|
*/
|
||||||
private static Object parseColorSystemColor( String value, List<String> params, Function<String, String> resolver ) {
|
private static Object parseColorSystemColor( String value, List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( params.size() < 1 )
|
if( params.size() < 1 )
|
||||||
throwMissingParametersException( value );
|
throw newMissingParametersException( value );
|
||||||
|
|
||||||
ColorUIResource systemColor = getSystemColor( params.get( 0 ) );
|
ColorUIResource systemColor = getSystemColor( params.get( 0 ) );
|
||||||
if( systemColor != null )
|
if( systemColor != null )
|
||||||
@@ -869,6 +914,7 @@ class UIDefaultsLoader
|
|||||||
*/
|
*/
|
||||||
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params,
|
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params,
|
||||||
Function<String, String> resolver )
|
Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
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
|
||||||
@@ -898,7 +944,9 @@ class UIDefaultsLoader
|
|||||||
* - lightness: a percentage 0-100%
|
* - lightness: a percentage 0-100%
|
||||||
* - alpha: a percentage 0-100%
|
* - alpha: a percentage 0-100%
|
||||||
*/
|
*/
|
||||||
private static ColorUIResource parseColorHslOrHsla( boolean hasAlpha, List<String> params ) {
|
private static ColorUIResource parseColorHslOrHsla( boolean hasAlpha, List<String> params )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
int hue = parseInteger( params.get( 0 ), 0, 360, false );
|
int hue = parseInteger( params.get( 0 ), 0, 360, false );
|
||||||
int saturation = parsePercentage( params.get( 1 ) );
|
int saturation = parsePercentage( params.get( 1 ) );
|
||||||
int lightness = parsePercentage( params.get( 2 ) );
|
int lightness = parsePercentage( params.get( 2 ) );
|
||||||
@@ -918,6 +966,7 @@ class UIDefaultsLoader
|
|||||||
*/
|
*/
|
||||||
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||||
List<String> params, Function<String, String> resolver )
|
List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parsePercentage( params.get( 1 ) );
|
int amount = parsePercentage( params.get( 1 ) );
|
||||||
@@ -961,7 +1010,9 @@ 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 ) {
|
private static Object parseColorFade( List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
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;
|
||||||
@@ -995,7 +1046,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 ) {
|
private static Object parseColorSpin( List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int amount = parseInteger( params.get( 1 ) );
|
int amount = parseInteger( params.get( 1 ) );
|
||||||
boolean derived = false;
|
boolean derived = false;
|
||||||
@@ -1023,6 +1076,7 @@ class UIDefaultsLoader
|
|||||||
*/
|
*/
|
||||||
private static Object parseColorChange( int hslIndex,
|
private static Object parseColorChange( int hslIndex,
|
||||||
List<String> params, Function<String, String> resolver )
|
List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
String colorStr = params.get( 0 );
|
String colorStr = params.get( 0 );
|
||||||
int value = (hslIndex == 0)
|
int value = (hslIndex == 0)
|
||||||
@@ -1051,7 +1105,9 @@ 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 ) {
|
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if( color1Str == null )
|
if( color1Str == null )
|
||||||
color1Str = params.get( i++ );
|
color1Str = params.get( i++ );
|
||||||
@@ -1078,7 +1134,9 @@ 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 ) {
|
private static Object parseColorContrast( List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
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 );
|
||||||
@@ -1104,7 +1162,9 @@ 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 ) {
|
private static ColorUIResource parseColorOver( List<String> params, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
String foregroundStr = params.get( 0 );
|
String foregroundStr = params.get( 0 );
|
||||||
String backgroundStr = params.get( 1 );
|
String backgroundStr = params.get( 1 );
|
||||||
|
|
||||||
@@ -1128,6 +1188,7 @@ 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 derived, Function<String, String> resolver )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
// parse base color
|
// parse base color
|
||||||
String resolvedColorStr = resolver.apply( colorStr );
|
String resolvedColorStr = resolver.apply( colorStr );
|
||||||
@@ -1159,7 +1220,9 @@ class UIDefaultsLoader
|
|||||||
/**
|
/**
|
||||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
||||||
*/
|
*/
|
||||||
private static Object parseFont( String value ) {
|
private static Object parseFont( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Object font = fontCache.get( value );
|
Object font = fontCache.get( value );
|
||||||
if( font != null )
|
if( font != null )
|
||||||
return font;
|
return font;
|
||||||
@@ -1257,7 +1320,9 @@ class UIDefaultsLoader
|
|||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int parsePercentage( String value ) {
|
private static int parsePercentage( String value )
|
||||||
|
throws IllegalArgumentException, NumberFormatException
|
||||||
|
{
|
||||||
if( !value.endsWith( "%" ) )
|
if( !value.endsWith( "%" ) )
|
||||||
throw new NumberFormatException( "invalid percentage '" + value + "'" );
|
throw new NumberFormatException( "invalid percentage '" + value + "'" );
|
||||||
|
|
||||||
@@ -1273,7 +1338,9 @@ class UIDefaultsLoader
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Boolean parseBoolean( String value ) {
|
private static Boolean parseBoolean( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
switch( value ) {
|
switch( value ) {
|
||||||
case "false": return false;
|
case "false": return false;
|
||||||
case "true": return true;
|
case "true": return true;
|
||||||
@@ -1281,13 +1348,17 @@ class UIDefaultsLoader
|
|||||||
throw new IllegalArgumentException( "invalid boolean '" + value + "'" );
|
throw new IllegalArgumentException( "invalid boolean '" + value + "'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Character parseCharacter( String value ) {
|
private static Character parseCharacter( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( value.length() != 1 )
|
if( value.length() != 1 )
|
||||||
throw new IllegalArgumentException( "invalid character '" + value + "'" );
|
throw new IllegalArgumentException( "invalid character '" + value + "'" );
|
||||||
return value.charAt( 0 );
|
return value.charAt( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer parseInteger( String value, int min, int max, boolean allowPercentage ) {
|
private static Integer parseInteger( String value, int min, int max, boolean allowPercentage )
|
||||||
|
throws IllegalArgumentException, NumberFormatException
|
||||||
|
{
|
||||||
if( allowPercentage && value.endsWith( "%" ) ) {
|
if( allowPercentage && value.endsWith( "%" ) ) {
|
||||||
int percent = parsePercentage( value );
|
int percent = parsePercentage( value );
|
||||||
return (max * percent) / 100;
|
return (max * percent) / 100;
|
||||||
@@ -1299,7 +1370,9 @@ class UIDefaultsLoader
|
|||||||
return integer;
|
return integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer parseInteger( String value ) {
|
private static Integer parseInteger( String value )
|
||||||
|
throws NumberFormatException
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt( value );
|
return Integer.parseInt( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
@@ -1307,7 +1380,9 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Number parseIntegerOrFloat( String value ) {
|
private static Number parseIntegerOrFloat( String value )
|
||||||
|
throws NumberFormatException
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt( value );
|
return Integer.parseInt( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
@@ -1319,7 +1394,9 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Float parseFloat( String value ) {
|
private static Float parseFloat( String value )
|
||||||
|
throws NumberFormatException
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
return Float.parseFloat( value );
|
return Float.parseFloat( value );
|
||||||
} catch( NumberFormatException ex ) {
|
} catch( NumberFormatException ex ) {
|
||||||
@@ -1327,35 +1404,45 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledInteger( String value ) {
|
private static ActiveValue parseScaledInteger( String value )
|
||||||
|
throws NumberFormatException
|
||||||
|
{
|
||||||
int val = parseInteger( value );
|
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 )
|
||||||
|
throws NumberFormatException
|
||||||
|
{
|
||||||
float val = parseFloat( value );
|
float val = parseFloat( value );
|
||||||
return t -> {
|
return t -> {
|
||||||
return UIScale.scale( val );
|
return UIScale.scale( val );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledInsets( String value ) {
|
private static ActiveValue parseScaledInsets( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Insets insets = parseInsets( value );
|
Insets insets = parseInsets( value );
|
||||||
return t -> {
|
return t -> {
|
||||||
return UIScale.scale( insets );
|
return UIScale.scale( insets );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledDimension( String value ) {
|
private static ActiveValue parseScaledDimension( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Dimension dimension = parseDimension( value );
|
Dimension dimension = parseDimension( value );
|
||||||
return t -> {
|
return t -> {
|
||||||
return UIScale.scale( dimension );
|
return UIScale.scale( dimension );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseGrayFilter( String value ) {
|
private static Object parseGrayFilter( String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
List<String> numbers = StringUtils.split( value, ',', true, false );
|
List<String> numbers = StringUtils.split( value, ',', true, false );
|
||||||
try {
|
try {
|
||||||
int brightness = Integer.parseInt( numbers.get( 0 ) );
|
int brightness = Integer.parseInt( numbers.get( 0 ) );
|
||||||
@@ -1399,6 +1486,86 @@ class UIDefaultsLoader
|
|||||||
return strs;
|
return strs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object invokeConstructorOrStaticMethod( Executable[] constructorsOrMethods,
|
||||||
|
List<String> parts, Function<String, String> resolver )
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
// order constructors/methods by parameter types:
|
||||||
|
// - String parameters to the end
|
||||||
|
// - int before float parameters
|
||||||
|
constructorsOrMethods = constructorsOrMethods.clone();
|
||||||
|
Arrays.sort( constructorsOrMethods, (c1, c2) -> {
|
||||||
|
Class<?>[] ptypes1 = c1.getParameterTypes();
|
||||||
|
Class<?>[] ptypes2 = c2.getParameterTypes();
|
||||||
|
if( ptypes1.length != ptypes2.length )
|
||||||
|
return ptypes1.length - ptypes2.length;
|
||||||
|
|
||||||
|
for( int i = 0; i < ptypes1.length; i++ ) {
|
||||||
|
Class<?> pt1 = ptypes1[i];
|
||||||
|
Class<?> pt2 = ptypes2[i];
|
||||||
|
|
||||||
|
if( pt1 == pt2 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// order methods with String parameters to the end
|
||||||
|
if( pt1 == String.class )
|
||||||
|
return 2;
|
||||||
|
if( pt2 == String.class )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
// order int before float
|
||||||
|
if( pt1 == int.class )
|
||||||
|
return -1;
|
||||||
|
if( pt2 == int.class )
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
// search for best constructor/method for given parameter values
|
||||||
|
for( Executable cm : constructorsOrMethods ) {
|
||||||
|
if( cm.getParameterCount() != parts.size() - 1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Object[] params = parseMethodParams( cm.getParameterTypes(), parts, resolver );
|
||||||
|
if( params == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// invoke constructor or static method
|
||||||
|
if( cm instanceof Constructor )
|
||||||
|
return ((Constructor<?>)cm).newInstance( params );
|
||||||
|
else
|
||||||
|
return ((Method)cm).invoke( null, params );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object[] parseMethodParams( Class<?>[] paramTypes, List<String> parts, Function<String, String> resolver ) {
|
||||||
|
Object[] params = new Object[paramTypes.length];
|
||||||
|
try {
|
||||||
|
for( int i = 0; i < params.length; i++ ) {
|
||||||
|
Class<?> paramType = paramTypes[i];
|
||||||
|
String paramValue = parts.get( i + 1 );
|
||||||
|
if( paramType == String.class )
|
||||||
|
params[i] = paramValue;
|
||||||
|
else if( paramType == boolean.class )
|
||||||
|
params[i] = parseBoolean( paramValue );
|
||||||
|
else if( paramType == int.class )
|
||||||
|
params[i] = parseInteger( paramValue );
|
||||||
|
else if( paramType == float.class )
|
||||||
|
params[i] = parseFloat( paramValue );
|
||||||
|
else if( paramType == Color.class )
|
||||||
|
params[i] = parseColorOrFunction( resolver.apply( paramValue ), resolver );
|
||||||
|
else
|
||||||
|
return null; // unsupported parameter type
|
||||||
|
}
|
||||||
|
} catch( IllegalArgumentException ex ) {
|
||||||
|
return null; // failed to parse parameter for expected parameter type
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For use in LazyValue to get value for given key from UIManager and report error
|
* For use in LazyValue to get value for given key from UIManager and report error
|
||||||
* if not found. If key is prefixed by '?', then no error is reported.
|
* if not found. If key is prefixed by '?', then no error is reported.
|
||||||
@@ -1416,7 +1583,7 @@ class UIDefaultsLoader
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void throwMissingParametersException( String value ) {
|
private static IllegalArgumentException newMissingParametersException( String value ) {
|
||||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
return new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ public class FlatInternalFrameCloseIcon
|
|||||||
|
|
||||||
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
||||||
|
|
||||||
float mx = width / 2;
|
float mx = width / 2f;
|
||||||
float my = height / 2;
|
float my = height / 2f;
|
||||||
float r = 3.25f;
|
float r = 3.25f;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ public class FlatTabbedPaneCloseIcon
|
|||||||
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
||||||
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
||||||
|
|
||||||
float mx = width / 2;
|
float mx = width / 2f;
|
||||||
float my = height / 2;
|
float my = height / 2f;
|
||||||
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.awt.Component;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
@@ -30,6 +29,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
* Base class for window icons.
|
* Base class for window icons.
|
||||||
*
|
*
|
||||||
* @uiDefault TitlePane.buttonSize Dimension
|
* @uiDefault TitlePane.buttonSize Dimension
|
||||||
|
* @uiDefault TitlePane.buttonSymbolHeight int
|
||||||
* @uiDefault TitlePane.buttonHoverBackground Color
|
* @uiDefault TitlePane.buttonHoverBackground Color
|
||||||
* @uiDefault TitlePane.buttonPressedBackground Color
|
* @uiDefault TitlePane.buttonPressedBackground Color
|
||||||
*
|
*
|
||||||
@@ -38,17 +38,22 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
public abstract class FlatWindowAbstractIcon
|
public abstract class FlatWindowAbstractIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private final int symbolHeight;
|
||||||
private final Color hoverBackground;
|
private final Color hoverBackground;
|
||||||
private final Color pressedBackground;
|
private final Color pressedBackground;
|
||||||
|
|
||||||
public FlatWindowAbstractIcon() {
|
/** @since 3.2 */
|
||||||
this( UIManager.getDimension( "TitlePane.buttonSize" ),
|
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||||
UIManager.getColor( "TitlePane.buttonHoverBackground" ),
|
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||||
UIManager.getColor( "TitlePane.buttonPressedBackground" ) );
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlatWindowAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) {
|
/** @since 3.2 */
|
||||||
|
protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
|
||||||
super( size.width, size.height, null );
|
super( size.width, size.height, null );
|
||||||
|
this.symbolHeight = symbolHeight;
|
||||||
this.hoverBackground = hoverBackground;
|
this.hoverBackground = hoverBackground;
|
||||||
this.pressedBackground = pressedBackground;
|
this.pressedBackground = pressedBackground;
|
||||||
}
|
}
|
||||||
@@ -80,4 +85,9 @@ public abstract class FlatWindowAbstractIcon
|
|||||||
protected Color getForeground( Component c ) {
|
protected Color getForeground( Component c ) {
|
||||||
return c.getForeground();
|
return c.getForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
protected int getSymbolHeight() {
|
||||||
|
return symbolHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ 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.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,18 +38,27 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
public class FlatWindowCloseIcon
|
public class FlatWindowCloseIcon
|
||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
private final Color hoverForeground = UIManager.getColor( "TitlePane.closeHoverForeground" );
|
private final Color hoverForeground;
|
||||||
private final Color pressedForeground = UIManager.getColor( "TitlePane.closePressedForeground" );
|
private final Color pressedForeground;
|
||||||
|
|
||||||
public FlatWindowCloseIcon() {
|
public FlatWindowCloseIcon() {
|
||||||
super( UIManager.getDimension( "TitlePane.buttonSize" ),
|
this( null );
|
||||||
UIManager.getColor( "TitlePane.closeHoverBackground" ),
|
}
|
||||||
UIManager.getColor( "TitlePane.closePressedBackground" ) );
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowCloseIcon( String windowStyle ) {
|
||||||
|
super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
|
||||||
|
|
||||||
|
hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
|
||||||
|
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int ix2 = ix + iwh - 1;
|
int ix2 = ix + iwh - 1;
|
||||||
|
|||||||
@@ -27,11 +27,17 @@ public class FlatWindowIconifyIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowIconifyIcon() {
|
public FlatWindowIconifyIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowIconifyIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iw = (int) (10 * scaleFactor);
|
int iw = (int) (getSymbolHeight() * scaleFactor);
|
||||||
int ih = (int) scaleFactor;
|
int ih = (int) scaleFactor;
|
||||||
int ix = x + ((width - iw) / 2);
|
int ix = x + ((width - iw) / 2);
|
||||||
int iy = y + ((height - ih) / 2);
|
int iy = y + ((height - ih) / 2);
|
||||||
|
|||||||
@@ -29,11 +29,17 @@ public class FlatWindowMaximizeIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowMaximizeIcon() {
|
public FlatWindowMaximizeIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowMaximizeIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
|||||||
@@ -32,18 +32,24 @@ public class FlatWindowRestoreIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowRestoreIcon() {
|
public FlatWindowRestoreIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowRestoreIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||||
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||||
|
|
||||||
int rwh = (int) (8 * scaleFactor);
|
int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
|
||||||
int ro2 = iwh - rwh;
|
int ro2 = iwh - rwh;
|
||||||
|
|
||||||
// upper-right rectangle
|
// upper-right rectangle
|
||||||
|
|||||||
@@ -502,9 +502,9 @@ class JsonParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHexDigit() {
|
private boolean isHexDigit() {
|
||||||
return current >= '0' && current <= '9'
|
return (current >= '0' && current <= '9')
|
||||||
|| current >= 'a' && current <= 'f'
|
|| (current >= 'a' && current <= 'f')
|
||||||
|| current >= 'A' && current <= 'F';
|
|| (current >= 'A' && current <= 'F');
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEndOfText() {
|
private boolean isEndOfText() {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class Location {
|
|||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (getClass() != obj.getClass()) {
|
if (!(obj instanceof Location)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Location other = (Location)obj;
|
Location other = (Location)obj;
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ 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;
|
||||||
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
|
import javax.swing.text.View;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
||||||
@@ -362,6 +364,9 @@ public class FlatButtonUI
|
|||||||
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
||||||
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
if( borderShared == null )
|
if( borderShared == null )
|
||||||
borderShared = new AtomicBoolean( true );
|
borderShared = new AtomicBoolean( true );
|
||||||
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, b, borderShared );
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, b, borderShared );
|
||||||
@@ -548,9 +553,45 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.paint(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
g = FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c );
|
||||||
|
|
||||||
|
AbstractButton b = (AbstractButton) c;
|
||||||
|
|
||||||
|
// layout
|
||||||
|
String clippedText = layout( b, b.getFontMetrics( b.getFont() ), b.getWidth(), b.getHeight() );
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
clearTextShiftOffset();
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
ButtonModel model = b.getModel();
|
||||||
|
if( model.isArmed() && model.isPressed() )
|
||||||
|
paintButtonPressed( g, b );
|
||||||
|
|
||||||
|
// paint icon
|
||||||
|
if( b.getIcon() != null )
|
||||||
|
paintIcon( g, b, iconR );
|
||||||
|
|
||||||
|
// paint text
|
||||||
|
if( clippedText != null && !clippedText.isEmpty() ) {
|
||||||
|
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null )
|
||||||
|
view.paint( g, textR ); // HTML text
|
||||||
|
else
|
||||||
|
paintText( g, b, textR, clippedText );
|
||||||
|
}
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
if( b.isFocusPainted() && b.hasFocus() )
|
||||||
|
paintFocus( g, b, viewR, textR, iconR );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -783,6 +824,67 @@ public class FlatButtonUI
|
|||||||
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBaseline( JComponent c, int width, int height ) {
|
||||||
|
return getBaselineImpl( c, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.getBaseline(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
|
static int getBaselineImpl( JComponent c, int width, int height ) {
|
||||||
|
if( width < 0 || height < 0 )
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
AbstractButton b = (AbstractButton) c;
|
||||||
|
String text = b.getText();
|
||||||
|
if( text == null || text.isEmpty() )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||||
|
layout( b, fm, width, height );
|
||||||
|
|
||||||
|
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null ) {
|
||||||
|
// HTML text
|
||||||
|
int baseline = BasicHTML.getHTMLBaseline( view, textR.width, textR.height );
|
||||||
|
return (baseline >= 0) ? textR.y + baseline : baseline;
|
||||||
|
} else
|
||||||
|
return textR.y + fm.getAscent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.layout(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
|
private static String layout( AbstractButton b, FontMetrics fm, int width, int height ) {
|
||||||
|
// compute view rectangle
|
||||||
|
Insets insets = b.getInsets();
|
||||||
|
viewR.setBounds( insets.left, insets.top,
|
||||||
|
width - insets.left - insets.right,
|
||||||
|
height - insets.top - insets.bottom );
|
||||||
|
|
||||||
|
// reset rectangles
|
||||||
|
textR.setBounds( 0, 0, 0, 0 );
|
||||||
|
iconR.setBounds( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
String text = b.getText();
|
||||||
|
return SwingUtilities.layoutCompoundLabel( b, fm, text, b.getIcon(),
|
||||||
|
b.getVerticalAlignment(), b.getHorizontalAlignment(),
|
||||||
|
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
|
||||||
|
viewR, iconR, textR,
|
||||||
|
(text != null) ? b.getIconTextGap() : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rectangle viewR = new Rectangle();
|
||||||
|
private static Rectangle textR = new Rectangle();
|
||||||
|
private static Rectangle iconR = new Rectangle();
|
||||||
|
|
||||||
//---- class FlatButtonListener -------------------------------------------
|
//---- class FlatButtonListener -------------------------------------------
|
||||||
|
|
||||||
protected class FlatButtonListener
|
protected class FlatButtonListener
|
||||||
|
|||||||
@@ -256,10 +256,14 @@ public class FlatCaret
|
|||||||
// select all
|
// select all
|
||||||
if( c instanceof JFormattedTextField ) {
|
if( c instanceof JFormattedTextField ) {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
if( getComponent() == null )
|
// Warning: do not use variables from outside of this runnable
|
||||||
|
// because they may be out-of-date when this runnable is executed
|
||||||
|
|
||||||
|
JTextComponent c2 = getComponent();
|
||||||
|
if( c2 == null )
|
||||||
return; // was deinstalled
|
return; // was deinstalled
|
||||||
|
|
||||||
select( 0, doc.getLength() );
|
select( 0, c2.getDocument().getLength() );
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
select( 0, doc.getLength() );
|
select( 0, doc.getLength() );
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.Component;
|
|||||||
import java.awt.ComponentOrientation;
|
import java.awt.ComponentOrientation;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@@ -48,10 +49,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.CellRendererPane;
|
import javax.swing.CellRendererPane;
|
||||||
|
import javax.swing.ComboBoxModel;
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.InputMap;
|
import javax.swing.InputMap;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JComboBox.KeySelectionManager;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@@ -102,7 +105,6 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault ComboBox.maximumRowCount int
|
* @uiDefault ComboBox.maximumRowCount int
|
||||||
* @uiDefault ComboBox.buttonStyle String auto (default), button, mac 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 ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
||||||
* @uiDefault ComboBox.focusedBackground Color optional
|
* @uiDefault ComboBox.focusedBackground Color optional
|
||||||
* @uiDefault ComboBox.disabledBackground Color
|
* @uiDefault ComboBox.disabledBackground Color
|
||||||
@@ -134,7 +136,6 @@ public class FlatComboBoxUI
|
|||||||
@Styleable protected int editorColumns;
|
@Styleable protected int editorColumns;
|
||||||
@Styleable protected String buttonStyle;
|
@Styleable protected String buttonStyle;
|
||||||
@Styleable protected String arrowType;
|
@Styleable protected String arrowType;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
|
|
||||||
private Color background;
|
private Color background;
|
||||||
@Styleable protected Color editableBackground;
|
@Styleable protected Color editableBackground;
|
||||||
@@ -182,6 +183,9 @@ public class FlatComboBoxUI
|
|||||||
private void installUIImpl( JComponent c ) {
|
private void installUIImpl( JComponent c ) {
|
||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
|
// install key selection manager that shows popup when Space key is pressed
|
||||||
|
comboBox.setKeySelectionManager( new FlatKeySelectionManager( comboBox.getKeySelectionManager() ) );
|
||||||
|
|
||||||
installStyle();
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +244,6 @@ public class FlatComboBoxUI
|
|||||||
editorColumns = UIManager.getInt( "ComboBox.editorColumns" );
|
editorColumns = UIManager.getInt( "ComboBox.editorColumns" );
|
||||||
buttonStyle = UIManager.getString( "ComboBox.buttonStyle" );
|
buttonStyle = UIManager.getString( "ComboBox.buttonStyle" );
|
||||||
arrowType = UIManager.getString( "Component.arrowType" );
|
arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
|
|
||||||
background = UIManager.getColor( "ComboBox.background" );
|
background = UIManager.getColor( "ComboBox.background" );
|
||||||
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
|
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
|
||||||
@@ -679,7 +682,7 @@ public class FlatComboBoxUI
|
|||||||
|
|
||||||
return (editableBackground != null && comboBox.isEditable()) ? editableBackground : background;
|
return (editableBackground != null && comboBox.isEditable()) ? editableBackground : background;
|
||||||
} else
|
} else
|
||||||
return isIntelliJTheme ? FlatUIUtils.getParentBackground( comboBox ) : disabledBackground;
|
return disabledBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( boolean enabled ) {
|
protected Color getForeground( boolean enabled ) {
|
||||||
@@ -986,6 +989,29 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// improve location of selected item in popup if list is large and scrollable
|
||||||
|
if( list.getHeight() == 0 ) {
|
||||||
|
// If popup is shown for the first time (or after a laf switch) and is scrollable,
|
||||||
|
// then BasicComboPopup scrolls the selected item to the top of the visible area.
|
||||||
|
// But for usability it would be better to have selected item somewhere
|
||||||
|
// in the middle of the visible area so that the user can see items above
|
||||||
|
// the selected item, which are usually more "important".
|
||||||
|
|
||||||
|
int selectedIndex = list.getSelectedIndex();
|
||||||
|
if( selectedIndex >= 1 ) {
|
||||||
|
int maximumRowCount = comboBox.getMaximumRowCount();
|
||||||
|
if( selectedIndex < maximumRowCount ) {
|
||||||
|
// selected item is in the first visible items --> scroll to top
|
||||||
|
list.scrollRectToVisible( new Rectangle() );
|
||||||
|
} else {
|
||||||
|
// scroll the selected item to the middle of the visible area
|
||||||
|
int firstVisibleIndex = Math.max( selectedIndex - (maximumRowCount / 2), 0 );
|
||||||
|
if( firstVisibleIndex > 0 )
|
||||||
|
list.ensureIndexIsVisible( firstVisibleIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
super.show( invoker, x, y );
|
super.show( invoker, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1209,4 +1235,46 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatKeySelectionManager --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key selection manager that delegates to the default manager.
|
||||||
|
* Shows the popup if Space key is pressed and "typed characters" buffer is empty.
|
||||||
|
* If items contain spaces (e.g. "a b") it is still possible to select them
|
||||||
|
* by pressing keys a, Space and b.
|
||||||
|
*/
|
||||||
|
private class FlatKeySelectionManager
|
||||||
|
implements JComboBox.KeySelectionManager, UIResource
|
||||||
|
{
|
||||||
|
private final KeySelectionManager delegate;
|
||||||
|
private final long timeFactor;
|
||||||
|
private long lastTime;
|
||||||
|
|
||||||
|
FlatKeySelectionManager( JComboBox.KeySelectionManager delegate ) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
|
||||||
|
Long value = (Long) UIManager.get( "ComboBox.timeFactor" );
|
||||||
|
timeFactor = (value != null) ? value : 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "rawtypes" )
|
||||||
|
@Override
|
||||||
|
public int selectionForKey( char aKey, ComboBoxModel aModel ) {
|
||||||
|
long time = EventQueue.getMostRecentEventTime();
|
||||||
|
long oldLastTime = lastTime;
|
||||||
|
lastTime = time;
|
||||||
|
|
||||||
|
// SPACE key shows popup if not yet visible
|
||||||
|
if( aKey == ' ' &&
|
||||||
|
time - oldLastTime >= timeFactor &&
|
||||||
|
!comboBox.isPopupVisible() )
|
||||||
|
{
|
||||||
|
comboBox.setPopupVisible( true );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return delegate.selectionForKey( aKey, aModel );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatEditorPaneUI -->
|
* <!-- FlatEditorPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault EditorPane.focusedBackground Color optional
|
* @uiDefault EditorPane.focusedBackground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -69,7 +68,6 @@ public class FlatEditorPaneUI
|
|||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
@Styleable protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
private Color background;
|
private Color background;
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color inactiveBackground;
|
@Styleable protected Color inactiveBackground;
|
||||||
@@ -101,7 +99,6 @@ public class FlatEditorPaneUI
|
|||||||
|
|
||||||
String prefix = getPropertyPrefix();
|
String prefix = getPropertyPrefix();
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
background = UIManager.getColor( prefix + ".background" );
|
background = UIManager.getColor( prefix + ".background" );
|
||||||
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
||||||
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
||||||
@@ -252,11 +249,11 @@ public class FlatEditorPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
paintBackground( g, getComponent(), focusedBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
|
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||||
g.setColor( FlatTextFieldUI.getBackground( c, isIntelliJTheme, focusedBackground ) );
|
g.setColor( FlatTextFieldUI.getBackground( c, focusedBackground ) );
|
||||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import java.beans.PropertyChangeEvent;
|
|||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
@@ -53,6 +54,7 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.icons.FlatFileViewDirectoryIcon;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
@@ -346,12 +348,12 @@ public class FlatFileChooserUI
|
|||||||
fileView.clearIconCache();
|
fileView.clearIconCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doNotUseSystemIcons() {
|
private static boolean doNotUseSystemIcons() {
|
||||||
// Java 17 32bit craches on Windows when using system icons
|
// Java 17 32bit craches on Windows when using system icons
|
||||||
// fixed in Java 18+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
// fixed in Java 18+, fix backported in Java 17.0.3+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||||
return SystemInfo.isWindows &&
|
return SystemInfo.isWindows &&
|
||||||
SystemInfo.isX86 &&
|
SystemInfo.isX86 &&
|
||||||
(SystemInfo.isJava_17_orLater && !SystemInfo.isJava_18_orLater);
|
(SystemInfo.isJava_17_orLater && SystemInfo.javaVersion < SystemInfo.toVersion( 17, 0, 3, 0 ));
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatFileView -------------------------------------------------
|
//---- class FlatFileView -------------------------------------------------
|
||||||
@@ -407,7 +409,7 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
protected final File[] files;
|
protected final File[] files;
|
||||||
protected final JToggleButton[] buttons;
|
protected final JToggleButton[] buttons;
|
||||||
protected final ButtonGroup buttonGroup;
|
protected final ButtonGroup buttonGroup = new ButtonGroup();
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
public FlatShortcutsPanel( JFileChooser fc ) {
|
public FlatShortcutsPanel( JFileChooser fc ) {
|
||||||
@@ -426,19 +428,22 @@ public class FlatFileChooserUI
|
|||||||
File[] files = getChooserShortcutPanelFiles( fsv );
|
File[] files = getChooserShortcutPanelFiles( fsv );
|
||||||
if( filesFunction != null )
|
if( filesFunction != null )
|
||||||
files = filesFunction.apply( files );
|
files = filesFunction.apply( files );
|
||||||
this.files = files;
|
|
||||||
|
|
||||||
// create toolbar buttons
|
// create toolbar buttons
|
||||||
buttons = new JToggleButton[files.length];
|
ArrayList<File> filesList = new ArrayList<>();
|
||||||
buttonGroup = new ButtonGroup();
|
ArrayList<JToggleButton> buttonsList = new ArrayList<>();
|
||||||
for( int i = 0; i < files.length; i++ ) {
|
for( File file : files ) {
|
||||||
// wrap drive path
|
if( file == null )
|
||||||
if( fsv.isFileSystemRoot( files[i] ) )
|
continue;
|
||||||
files[i] = fsv.createFileObject( files[i].getAbsolutePath() );
|
|
||||||
|
// wrap drive path
|
||||||
|
if( fsv.isFileSystemRoot( file ) )
|
||||||
|
file = fsv.createFileObject( file.getAbsolutePath() );
|
||||||
|
|
||||||
File file = files[i];
|
|
||||||
String name = getDisplayName( fsv, file );
|
String name = getDisplayName( fsv, file );
|
||||||
Icon icon = getIcon( fsv, file );
|
Icon icon = getIcon( fsv, file );
|
||||||
|
if( name == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
// remove path from name
|
// remove path from name
|
||||||
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
||||||
@@ -453,15 +458,21 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
// create button
|
// create button
|
||||||
JToggleButton button = createButton( name, icon );
|
JToggleButton button = createButton( name, icon );
|
||||||
|
File f = file;
|
||||||
button.addActionListener( e -> {
|
button.addActionListener( e -> {
|
||||||
fc.setCurrentDirectory( file );
|
fc.setCurrentDirectory( f );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
add( button );
|
add( button );
|
||||||
buttonGroup.add( button );
|
buttonGroup.add( button );
|
||||||
buttons[i] = button;
|
|
||||||
|
filesList.add( file );
|
||||||
|
buttonsList.add( button );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.files = filesList.toArray( new File[filesList.size()] );
|
||||||
|
this.buttons = buttonsList.toArray( new JToggleButton[buttonsList.size()] );
|
||||||
|
|
||||||
directoryChanged( fc.getCurrentDirectory() );
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,6 +537,9 @@ public class FlatFileChooserUI
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( doNotUseSystemIcons() )
|
||||||
|
return new FlatFileViewDirectoryIcon();
|
||||||
|
|
||||||
// Java 17+ supports getting larger system icons
|
// Java 17+ supports getting larger system icons
|
||||||
try {
|
try {
|
||||||
if( SystemInfo.isJava_17_orLater ) {
|
if( SystemInfo.isJava_17_orLater ) {
|
||||||
@@ -541,10 +555,12 @@ public class FlatFileChooserUI
|
|||||||
return new ImageIcon( image );
|
return new ImageIcon( image );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch( IllegalAccessException ex ) {
|
|
||||||
// do not log because access may be denied via VM option '--illegal-access=deny'
|
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
// do not log InaccessibleObjectException because access
|
||||||
|
// may be denied via VM option '--illegal-access=deny' (default in Java 16)
|
||||||
|
// (not catching InaccessibleObjectException here because it is new in Java 9, but FlatLaf also runs on Java 8)
|
||||||
|
if( !"java.lang.reflect.InaccessibleObjectException".equals( ex.getClass().getName() ) )
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
}
|
}
|
||||||
|
|
||||||
// get system icon in default size 16x16
|
// get system icon in default size 16x16
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
* <!-- FlatTextFieldUI -->
|
* <!-- FlatTextFieldUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||||
* @uiDefault FormattedTextField.focusedBackground Color optional
|
* @uiDefault FormattedTextField.focusedBackground Color optional
|
||||||
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.Rectangle;
|
|||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
@@ -179,7 +180,7 @@ public class FlatLabelUI
|
|||||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
||||||
|
|
||||||
String lowerText = text.toLowerCase();
|
String lowerText = text.toLowerCase( Locale.ENGLISH );
|
||||||
int headIndex;
|
int headIndex;
|
||||||
int styleIndex;
|
int styleIndex;
|
||||||
|
|
||||||
@@ -228,7 +229,7 @@ public class FlatLabelUI
|
|||||||
int tagBegin = i + 1;
|
int tagBegin = i + 1;
|
||||||
for( i += 2; i < textLength; i++ ) {
|
for( i += 2; i < textLength; i++ ) {
|
||||||
if( !Character.isLetterOrDigit( text.charAt( i ) ) ) {
|
if( !Character.isLetterOrDigit( text.charAt( i ) ) ) {
|
||||||
String tag = text.substring( tagBegin, i ).toLowerCase();
|
String tag = text.substring( tagBegin, i ).toLowerCase( Locale.ENGLISH );
|
||||||
if( tagsUseFontSizeSet.contains( tag ) )
|
if( tagsUseFontSizeSet.contains( tag ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -301,7 +301,8 @@ public class FlatListUI
|
|||||||
// get renderer component
|
// get renderer component
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
|
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
|
||||||
dataModel.getElementAt( row ), row, isSelected, list.hasFocus() && (row == leadIndex) );
|
dataModel.getElementAt( row ), row, isSelected,
|
||||||
|
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );
|
||||||
|
|
||||||
//
|
//
|
||||||
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
|
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
|
||||||
|
|||||||
@@ -456,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,
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -31,6 +33,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
*/
|
*/
|
||||||
class FlatNativeLibrary
|
class FlatNativeLibrary
|
||||||
{
|
{
|
||||||
|
private static boolean initialized;
|
||||||
private static NativeLibrary nativeLibrary;
|
private static NativeLibrary nativeLibrary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,28 +46,46 @@ class FlatNativeLibrary
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void initialize() {
|
private static void initialize() {
|
||||||
if( nativeLibrary != null )
|
if( initialized )
|
||||||
|
return;
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_NATIVE_LIBRARY, true ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String libraryName;
|
String classifier;
|
||||||
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
|
String ext;
|
||||||
// Windows: requires Windows 10/11 (x86 or x86_64)
|
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) {
|
||||||
|
// Windows: requires Windows 10/11 (x86, x86_64 or aarch64)
|
||||||
|
|
||||||
libraryName = "flatlaf-windows-x86";
|
if( SystemInfo.isAARCH64 )
|
||||||
if( SystemInfo.isX86_64 )
|
classifier = "windows-arm64";
|
||||||
libraryName += "_64";
|
else if( SystemInfo.isX86_64 )
|
||||||
|
classifier = "windows-x86_64";
|
||||||
|
else
|
||||||
|
classifier = "windows-x86";
|
||||||
|
|
||||||
|
ext = "dll";
|
||||||
|
|
||||||
|
// Do not load jawt.dll (part of JRE) here explicitly because
|
||||||
|
// the FlatLaf native library flatlaf.dll may be loaded very early on Windows
|
||||||
|
// (e.g. from class com.formdev.flatlaf.util.SystemInfo) and before AWT is
|
||||||
|
// initialized (and awt.dll is loaded). Loading jawt.dll also loads awt.dll.
|
||||||
|
// In Java 8, loading jawt.dll before AWT is initialized may load
|
||||||
|
// a wrong version of awt.dll if a newer Java version (e.g. 19)
|
||||||
|
// is in PATH environment variable. Then Java 19 awt.dll and Java 8 awt.dll
|
||||||
|
// are loaded at same time and calling JAWT_GetAWT() crashes the application.
|
||||||
|
//
|
||||||
|
// To avoid this, flatlaf.dll is not linked to jawt.dll,
|
||||||
|
// which avoids loading jawt.dll when flatlaf.dll is loaded.
|
||||||
|
// Instead flatlaf.dll dynamically loads jawt.dll when first used,
|
||||||
|
// which is guaranteed after AWT initialization.
|
||||||
|
|
||||||
// In Java 8, load jawt.dll (part of JRE) explicitly because it
|
|
||||||
// is not found when running application with <jdk>/bin/java.exe.
|
|
||||||
// When using <jdk>/jre/bin/java.exe, it is found.
|
|
||||||
// jawt.dll is located in <jdk>/jre/bin/.
|
|
||||||
// Java 9 and later do not have this problem,
|
|
||||||
// but load jawt.dll anyway to be on the safe side.
|
|
||||||
loadJAWT();
|
|
||||||
} 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 +97,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 +121,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 );
|
||||||
|
}
|
||||||
@@ -66,7 +66,6 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* <!-- FlatTextFieldUI -->
|
* <!-- FlatTextFieldUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault PasswordField.placeholderForeground Color
|
* @uiDefault PasswordField.placeholderForeground Color
|
||||||
* @uiDefault PasswordField.focusedBackground Color optional
|
* @uiDefault PasswordField.focusedBackground Color optional
|
||||||
* @uiDefault PasswordField.iconTextGap int optional, default is 4
|
* @uiDefault PasswordField.iconTextGap int optional, default is 4
|
||||||
|
|||||||
@@ -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,21 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether popup overlaps a heavy weight component
|
||||||
|
if( !forceHeavyWeight && overlapsHeavyWeightComponent( owner, contents, x, y ) )
|
||||||
|
forceHeavyWeight = true;
|
||||||
|
|
||||||
// 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 +185,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;
|
|
||||||
|
private int getBorderCornerRadius( Component owner, Component contents ) {
|
||||||
|
String uiKey =
|
||||||
|
(contents instanceof BasicComboPopup) ? "ComboBox.borderCornerRadius" :
|
||||||
|
(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( contents instanceof JComponent ) {
|
return UIManager.get( uiKey );
|
||||||
Boolean b = FlatClientProperties.clientPropertyBooleanStrict( (JComponent) contents, clientKey, null );
|
|
||||||
if( b != null )
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return UIManager.getBoolean( uiKey );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -300,9 +339,90 @@ 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean overlapsHeavyWeightComponent( Component owner, Component contents, int x, int y ) {
|
||||||
|
Window window = SwingUtilities.getWindowAncestor( owner );
|
||||||
|
if( window == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Rectangle r = new Rectangle( new Point( x, y ), contents.getPreferredSize() );
|
||||||
|
return overlapsHeavyWeightComponent( window, r );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean overlapsHeavyWeightComponent( Component parent, Rectangle r ) {
|
||||||
|
if( !parent.isVisible() || !r.intersects( parent.getBounds() ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !parent.isLightweight() && !(parent instanceof Window) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( parent instanceof Container ) {
|
||||||
|
Rectangle r2 = new Rectangle( r.x - parent.getX(), r.y - parent.getY(), r.width, r.height );
|
||||||
|
for( Component c : ((Container)parent).getComponents() ) {
|
||||||
|
if( overlapsHeavyWeightComponent( c, r2 ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class NonFlashingPopup ---------------------------------------------
|
//---- class NonFlashingPopup ---------------------------------------------
|
||||||
|
|
||||||
private class NonFlashingPopup
|
private static class NonFlashingPopup
|
||||||
extends Popup
|
extends Popup
|
||||||
{
|
{
|
||||||
private Popup delegate;
|
private Popup delegate;
|
||||||
@@ -431,6 +551,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;
|
||||||
@@ -192,27 +193,38 @@ public class FlatPopupMenuUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Popup getPopup( JPopupMenu popup, int x, int y ) {
|
public Popup getPopup( JPopupMenu popup, int x, int y ) {
|
||||||
|
Dimension popupSize = popup.getPreferredSize();
|
||||||
|
Rectangle screenBounds = getScreenBoundsAt( x, y );
|
||||||
|
|
||||||
|
// make sure that popup does not overlap any task/side bar
|
||||||
|
if( x + popupSize.width > screenBounds.x + screenBounds.width )
|
||||||
|
x = screenBounds.x + screenBounds.width - popupSize.width;
|
||||||
|
if( y + popupSize.height > screenBounds.y + screenBounds.height )
|
||||||
|
y = screenBounds.y + screenBounds.height - popupSize.height;
|
||||||
|
if( x < screenBounds.x )
|
||||||
|
x = screenBounds.x;
|
||||||
|
if( y < screenBounds.y )
|
||||||
|
y = screenBounds.y;
|
||||||
|
|
||||||
// do not add scroller to combobox popups or to popups that already have a scroll pane
|
// do not add scroller to combobox popups or to popups that already have a scroll pane
|
||||||
if( popup instanceof BasicComboPopup ||
|
if( popup instanceof BasicComboPopup ||
|
||||||
(popup.getComponentCount() > 0 && popup.getComponent( 0 ) instanceof JScrollPane) )
|
(popup.getComponentCount() > 0 && popup.getComponent( 0 ) instanceof JScrollPane) )
|
||||||
return super.getPopup( popup, x, y );
|
return super.getPopup( popup, x, y );
|
||||||
|
|
||||||
// do not add scroller if popup fits into screen
|
// do not add scroller if popup fits into screen
|
||||||
Dimension prefSize = popup.getPreferredSize();
|
if( popupSize.height <= screenBounds.height )
|
||||||
int screenHeight = getScreenHeightAt( x, y );
|
|
||||||
if( prefSize.height <= screenHeight )
|
|
||||||
return super.getPopup( popup, x, y );
|
return super.getPopup( popup, x, y );
|
||||||
|
|
||||||
// create scroller
|
// create scroller
|
||||||
FlatPopupScroller scroller = new FlatPopupScroller( popup );
|
FlatPopupScroller scroller = new FlatPopupScroller( popup );
|
||||||
scroller.setPreferredSize( new Dimension( prefSize.width, screenHeight ) );
|
scroller.setPreferredSize( new Dimension( popupSize.width, screenBounds.height ) );
|
||||||
|
|
||||||
// create popup
|
// create popup
|
||||||
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
||||||
return popupFactory.getPopup( popup.getInvoker(), scroller, x, y );
|
return popupFactory.getPopup( popup.getInvoker(), scroller, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getScreenHeightAt( int x, int y ) {
|
private Rectangle getScreenBoundsAt( int x, int y ) {
|
||||||
// find GraphicsConfiguration at popup location (similar to JPopupMenu.getCurrentGraphicsConfiguration())
|
// find GraphicsConfiguration at popup location (similar to JPopupMenu.getCurrentGraphicsConfiguration())
|
||||||
GraphicsConfiguration gc = null;
|
GraphicsConfiguration gc = null;
|
||||||
for( GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) {
|
for( GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) {
|
||||||
@@ -233,7 +245,7 @@ public class FlatPopupMenuUI
|
|||||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||||
Rectangle screenBounds = (gc != null) ? gc.getBounds() : new Rectangle( toolkit.getScreenSize() );
|
Rectangle screenBounds = (gc != null) ? gc.getBounds() : new Rectangle( toolkit.getScreenSize() );
|
||||||
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
||||||
return screenBounds.height - screenInsets.top - screenInsets.bottom;
|
return FlatUIUtils.subtractInsets( screenBounds, screenInsets );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatPopupMenuLayout ------------------------------------------
|
//---- class FlatPopupMenuLayout ------------------------------------------
|
||||||
@@ -297,6 +309,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 ) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import javax.swing.CellRendererPane;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
@@ -208,6 +209,9 @@ public class FlatRadioButtonUI
|
|||||||
return ((FlatCheckBoxIcon)icon).applyStyleProperty( key, value );
|
return ((FlatCheckBoxIcon)icon).applyStyleProperty( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
||||||
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, b, key, value );
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, b, key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,20 +279,27 @@ public class FlatRadioButtonUI
|
|||||||
int focusWidth = getIconFocusWidth( c );
|
int focusWidth = getIconFocusWidth( c );
|
||||||
if( focusWidth > 0 ) {
|
if( focusWidth > 0 ) {
|
||||||
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
||||||
|
int halign = ((AbstractButton)c).getHorizontalAlignment();
|
||||||
|
if( halign == SwingConstants.LEADING )
|
||||||
|
halign = ltr ? SwingConstants.LEFT : SwingConstants.RIGHT;
|
||||||
|
else if( halign == SwingConstants.TRAILING )
|
||||||
|
halign = ltr ? SwingConstants.RIGHT : SwingConstants.LEFT;
|
||||||
|
|
||||||
Insets insets = c.getInsets( tempInsets );
|
Insets insets = c.getInsets( tempInsets );
|
||||||
int leftOrRightInset = ltr ? insets.left : insets.right;
|
if( (focusWidth > insets.left || focusWidth > insets.right) &&
|
||||||
if( focusWidth > leftOrRightInset ) {
|
(halign == SwingConstants.LEFT || halign == SwingConstants.RIGHT) )
|
||||||
|
{
|
||||||
// The left (or right) inset is smaller than the focus width, which may be
|
// The left (or right) inset is smaller than the focus width, which may be
|
||||||
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
|
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
|
||||||
// In this case the width has been increased in getPreferredSize() and
|
// In this case the width has been increased in getPreferredSize() and
|
||||||
// here it is necessary to fix icon and text painting location.
|
// here it is necessary to fix icon and text painting location.
|
||||||
int offset = focusWidth - leftOrRightInset;
|
int offset = (halign == SwingConstants.LEFT)
|
||||||
if( !ltr )
|
? Math.max( focusWidth - insets.left, 0 )
|
||||||
offset = -offset;
|
: -Math.max( focusWidth - insets.right, 0 );
|
||||||
|
|
||||||
// move the graphics origin to the left (or right)
|
// move the graphics origin to the left (or right)
|
||||||
g.translate( offset, 0 );
|
g.translate( offset, 0 );
|
||||||
super.paint( g, c );
|
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
||||||
g.translate( -offset, 0 );
|
g.translate( -offset, 0 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -325,6 +336,11 @@ public class FlatRadioButtonUI
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBaseline( JComponent c, int width, int height ) {
|
||||||
|
return FlatButtonUI.getBaselineImpl( c, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatRadioButtonListener --------------------------------------
|
//---- class FlatRadioButtonListener --------------------------------------
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.IllegalComponentStateException;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
import java.awt.LayoutManager2;
|
import java.awt.LayoutManager2;
|
||||||
@@ -366,6 +367,11 @@ public class FlatRootPaneUI
|
|||||||
case FlatClientProperties.GLASS_PANE_FULL_HEIGHT:
|
case FlatClientProperties.GLASS_PANE_FULL_HEIGHT:
|
||||||
rootPane.revalidate();
|
rootPane.revalidate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.WINDOW_STYLE:
|
||||||
|
if( rootPane.isDisplayable() )
|
||||||
|
throw new IllegalComponentStateException( "The client property 'Window.style' must be set before the window becomes displayable." );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +557,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -360,8 +360,8 @@ public class FlatScrollPaneUI
|
|||||||
protected void updateViewport( PropertyChangeEvent e ) {
|
protected void updateViewport( PropertyChangeEvent e ) {
|
||||||
super.updateViewport( e );
|
super.updateViewport( e );
|
||||||
|
|
||||||
JViewport oldViewport = (JViewport) (e.getOldValue());
|
JViewport oldViewport = (JViewport) e.getOldValue();
|
||||||
JViewport newViewport = (JViewport) (e.getNewValue());
|
JViewport newViewport = (JViewport) e.getNewValue();
|
||||||
|
|
||||||
removeViewportListeners( oldViewport );
|
removeViewportListeners( oldViewport );
|
||||||
addViewportListeners( newViewport );
|
addViewportListeners( newViewport );
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Spinner.buttonStyle String button (default), mac 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 Spinner.disabledBackground Color
|
* @uiDefault Spinner.disabledBackground Color
|
||||||
* @uiDefault Spinner.disabledForeground Color
|
* @uiDefault Spinner.disabledForeground Color
|
||||||
* @uiDefault Spinner.focusedBackground Color optional
|
* @uiDefault Spinner.focusedBackground Color optional
|
||||||
@@ -92,7 +91,6 @@ public class FlatSpinnerUI
|
|||||||
@Styleable protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
@Styleable protected String buttonStyle;
|
@Styleable protected String buttonStyle;
|
||||||
@Styleable protected String arrowType;
|
@Styleable protected String arrowType;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color disabledForeground;
|
@Styleable protected Color disabledForeground;
|
||||||
@Styleable protected Color focusedBackground;
|
@Styleable protected Color focusedBackground;
|
||||||
@@ -129,7 +127,6 @@ public class FlatSpinnerUI
|
|||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
buttonStyle = UIManager.getString( "Spinner.buttonStyle" );
|
buttonStyle = UIManager.getString( "Spinner.buttonStyle" );
|
||||||
arrowType = UIManager.getString( "Component.arrowType" );
|
arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
disabledBackground = UIManager.getColor( "Spinner.disabledBackground" );
|
disabledBackground = UIManager.getColor( "Spinner.disabledBackground" );
|
||||||
disabledForeground = UIManager.getColor( "Spinner.disabledForeground" );
|
disabledForeground = UIManager.getColor( "Spinner.disabledForeground" );
|
||||||
focusedBackground = UIManager.getColor( "Spinner.focusedBackground" );
|
focusedBackground = UIManager.getColor( "Spinner.focusedBackground" );
|
||||||
@@ -316,7 +313,7 @@ public class FlatSpinnerUI
|
|||||||
|
|
||||||
return background;
|
return background;
|
||||||
} else
|
} else
|
||||||
return isIntelliJTheme ? FlatUIUtils.getParentBackground( spinner ) : disabledBackground;
|
return disabledBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( boolean enabled ) {
|
protected Color getForeground( boolean enabled ) {
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ public class FlatSplitPaneUI
|
|||||||
@Styleable protected Color oneTouchHoverArrowColor;
|
@Styleable protected Color oneTouchHoverArrowColor;
|
||||||
@Styleable protected Color oneTouchPressedArrowColor;
|
@Styleable protected Color oneTouchPressedArrowColor;
|
||||||
|
|
||||||
private PropertyChangeListener propertyChangeListener;
|
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
@@ -126,19 +125,9 @@ public class FlatSplitPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installListeners() {
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
super.installListeners();
|
return FlatStylingSupport.createPropertyChangeListener( splitPane, this::installStyle,
|
||||||
|
super.createPropertyChangeListener() );
|
||||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( splitPane, this::installStyle, null );
|
|
||||||
splitPane.addPropertyChangeListener( propertyChangeListener );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void uninstallListeners() {
|
|
||||||
super.uninstallListeners();
|
|
||||||
|
|
||||||
splitPane.removePropertyChangeListener( propertyChangeListener );
|
|
||||||
propertyChangeListener = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -100,15 +100,15 @@ public class FlatStylingSupport
|
|||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
public interface StyleableUI {
|
public interface StyleableUI {
|
||||||
Map<String, Class<?>> getStyleableInfos( JComponent c );
|
Map<String, Class<?>> getStyleableInfos( JComponent c ) throws IllegalArgumentException;
|
||||||
/** @since 2.5 */ Object getStyleableValue( JComponent c, String key );
|
/** @since 2.5 */ Object getStyleableValue( JComponent c, String key ) throws IllegalArgumentException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
public interface StyleableBorder {
|
public interface StyleableBorder {
|
||||||
Object applyStyleProperty( String key, Object value );
|
Object applyStyleProperty( String key, Object value );
|
||||||
Map<String, Class<?>> getStyleableInfos();
|
Map<String, Class<?>> getStyleableInfos() throws IllegalArgumentException;
|
||||||
/** @since 2.5 */ Object getStyleableValue( String key );
|
/** @since 2.5 */ Object getStyleableValue( String key ) throws IllegalArgumentException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2.5 */
|
/** @since 2.5 */
|
||||||
@@ -135,7 +135,9 @@ public class FlatStylingSupport
|
|||||||
return getStyle( c ) != null || getStyleClass( c ) != null;
|
return getStyle( c ) != null || getStyleClass( c ) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getResolvedStyle( JComponent c, String type ) {
|
public static Object getResolvedStyle( JComponent c, String type )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Object style = getStyle( c );
|
Object style = getStyle( c );
|
||||||
Object styleClass = getStyleClass( c );
|
Object styleClass = getStyleClass( c );
|
||||||
Object styleForClasses = getStyleForClasses( styleClass, type );
|
Object styleForClasses = getStyleForClasses( styleClass, type );
|
||||||
@@ -175,7 +177,9 @@ public class FlatStylingSupport
|
|||||||
* @param type the type of the component
|
* @param type the type of the component
|
||||||
* @return the styles
|
* @return the styles
|
||||||
*/
|
*/
|
||||||
public static Object getStyleForClasses( Object styleClass, String type ) {
|
public static Object getStyleForClasses( Object styleClass, String type )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( styleClass == null )
|
if( styleClass == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -198,7 +202,9 @@ public class FlatStylingSupport
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object getStyleForClass( String styleClass, String type ) {
|
private static Object getStyleForClass( String styleClass, String type )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
return joinStyles(
|
return joinStyles(
|
||||||
UIManager.get( "[style]." + styleClass ),
|
UIManager.get( "[style]." + styleClass ),
|
||||||
UIManager.get( "[style]" + type + '.' + styleClass ) );
|
UIManager.get( "[style]" + type + '.' + styleClass ) );
|
||||||
@@ -218,7 +224,9 @@ public class FlatStylingSupport
|
|||||||
* @return new joined style
|
* @return new joined style
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
public static Object joinStyles( Object style1, Object style2 ) {
|
public static Object joinStyles( Object style1, Object style2 )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( style1 == null )
|
if( style1 == null )
|
||||||
return style2;
|
return style2;
|
||||||
if( style2 == null )
|
if( style2 == null )
|
||||||
@@ -278,6 +286,7 @@ public class FlatStylingSupport
|
|||||||
* @throws IllegalArgumentException on syntax errors
|
* @throws IllegalArgumentException on syntax errors
|
||||||
* @throws ClassCastException if value type does not fit to expected type
|
* @throws ClassCastException if value type does not fit to expected type
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings( "ReturnValueIgnored" ) // Error Prone
|
||||||
public static Map<String, Object> parseAndApply( Map<String, Object> oldStyleValues,
|
public static Map<String, Object> parseAndApply( Map<String, Object> oldStyleValues,
|
||||||
Object style, BiFunction<String, Object, Object> applyProperty )
|
Object style, BiFunction<String, Object, Object> applyProperty )
|
||||||
throws UnknownStyleException, IllegalArgumentException
|
throws UnknownStyleException, IllegalArgumentException
|
||||||
@@ -379,7 +388,9 @@ public class FlatStylingSupport
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object parseValue( String key, String value ) {
|
private static Object parseValue( String key, String value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
// simple reference
|
// simple reference
|
||||||
if( value.startsWith( "$" ) )
|
if( value.startsWith( "$" ) )
|
||||||
return UIManager.get( value.substring( 1 ) );
|
return UIManager.get( value.substring( 1 ) );
|
||||||
@@ -474,7 +485,9 @@ public class FlatStylingSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object applyToField( Field f, Object obj, Object value, boolean useMethodHandles ) {
|
private static Object applyToField( Field f, Object obj, Object value, boolean useMethodHandles )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
checkValidField( f );
|
checkValidField( f );
|
||||||
|
|
||||||
if( useMethodHandles && obj instanceof StyleableLookupProvider ) {
|
if( useMethodHandles && obj instanceof StyleableLookupProvider ) {
|
||||||
@@ -504,7 +517,9 @@ public class FlatStylingSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object getFieldValue( Field f, Object obj, boolean useMethodHandles ) {
|
private static Object getFieldValue( Field f, Object obj, boolean useMethodHandles )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
checkValidField( f );
|
checkValidField( f );
|
||||||
|
|
||||||
if( useMethodHandles && obj instanceof StyleableLookupProvider ) {
|
if( useMethodHandles && obj instanceof StyleableLookupProvider ) {
|
||||||
@@ -529,7 +544,9 @@ public class FlatStylingSupport
|
|||||||
return new IllegalArgumentException( "failed to access field '" + f.getDeclaringClass().getName() + "." + f.getName() + "'", ex );
|
return new IllegalArgumentException( "failed to access field '" + f.getDeclaringClass().getName() + "." + f.getName() + "'", ex );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkValidField( Field f ) {
|
private static void checkValidField( Field f )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
if( !isValidField( f ) )
|
if( !isValidField( f ) )
|
||||||
throw new IllegalArgumentException( "field '" + f.getDeclaringClass().getName() + "." + f.getName() + "' is final or static" );
|
throw new IllegalArgumentException( "field '" + f.getDeclaringClass().getName() + "." + f.getName() + "' is final or static" );
|
||||||
}
|
}
|
||||||
@@ -539,7 +556,9 @@ public class FlatStylingSupport
|
|||||||
return (modifiers & (Modifier.FINAL|Modifier.STATIC)) == 0 && !f.isSynthetic();
|
return (modifiers & (Modifier.FINAL|Modifier.STATIC)) == 0 && !f.isSynthetic();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Field getStyleableField( StyleableField styleableField ) {
|
private static Field getStyleableField( StyleableField styleableField )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
String fieldName = styleableField.fieldName();
|
String fieldName = styleableField.fieldName();
|
||||||
if( fieldName.isEmpty() )
|
if( fieldName.isEmpty() )
|
||||||
fieldName = styleableField.key();
|
fieldName = styleableField.key();
|
||||||
@@ -647,6 +666,7 @@ public class FlatStylingSupport
|
|||||||
|
|
||||||
static Object applyToAnnotatedObjectOrBorder( Object obj, String key, Object value,
|
static Object applyToAnnotatedObjectOrBorder( Object obj, String key, Object value,
|
||||||
JComponent c, AtomicBoolean borderShared )
|
JComponent c, AtomicBoolean borderShared )
|
||||||
|
throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return applyToAnnotatedObject( obj, key, value );
|
return applyToAnnotatedObject( obj, key, value );
|
||||||
@@ -695,7 +715,9 @@ public class FlatStylingSupport
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Border cloneBorder( Border border ) {
|
static Border cloneBorder( Border border )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Class<? extends Border> borderClass = border.getClass();
|
Class<? extends Border> borderClass = border.getClass();
|
||||||
try {
|
try {
|
||||||
return borderClass.getDeclaredConstructor().newInstance();
|
return borderClass.getDeclaredConstructor().newInstance();
|
||||||
@@ -704,7 +726,9 @@ public class FlatStylingSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Icon cloneIcon( Icon icon ) {
|
static Icon cloneIcon( Icon icon )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Class<? extends Icon> iconClass = icon.getClass();
|
Class<? extends Icon> iconClass = icon.getClass();
|
||||||
try {
|
try {
|
||||||
return iconClass.getDeclaredConstructor().newInstance();
|
return iconClass.getDeclaredConstructor().newInstance();
|
||||||
@@ -717,11 +741,15 @@ public class FlatStylingSupport
|
|||||||
* Returns a map of all fields annotated with {@link Styleable}.
|
* Returns a map of all fields annotated with {@link Styleable}.
|
||||||
* The key is the name of the field and the value the type of the field.
|
* The key is the name of the field and the value the type of the field.
|
||||||
*/
|
*/
|
||||||
public static Map<String, Class<?>> getAnnotatedStyleableInfos( Object obj ) {
|
public static Map<String, Class<?>> getAnnotatedStyleableInfos( Object obj )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
return getAnnotatedStyleableInfos( obj, null );
|
return getAnnotatedStyleableInfos( obj, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Class<?>> getAnnotatedStyleableInfos( Object obj, Border border ) {
|
public static Map<String, Class<?>> getAnnotatedStyleableInfos( Object obj, Border border )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
Map<String, Class<?>> infos = new StyleableInfosMap<>();
|
Map<String, Class<?>> infos = new StyleableInfosMap<>();
|
||||||
collectAnnotatedStyleableInfos( obj, infos );
|
collectAnnotatedStyleableInfos( obj, infos );
|
||||||
collectStyleableInfos( border, infos );
|
collectStyleableInfos( border, infos );
|
||||||
@@ -732,7 +760,9 @@ public class FlatStylingSupport
|
|||||||
* Search for all fields annotated with {@link Styleable} and add them to the given map.
|
* Search for all fields annotated with {@link Styleable} and add them to the given map.
|
||||||
* The key is the name of the field and the value the type of the field.
|
* The key is the name of the field and the value the type of the field.
|
||||||
*/
|
*/
|
||||||
public static void collectAnnotatedStyleableInfos( Object obj, Map<String, Class<?>> infos ) {
|
public static void collectAnnotatedStyleableInfos( Object obj, Map<String, Class<?>> infos )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
HashSet<String> processedFields = new HashSet<>();
|
HashSet<String> processedFields = new HashSet<>();
|
||||||
Class<?> cls = obj.getClass();
|
Class<?> cls = obj.getClass();
|
||||||
|
|
||||||
@@ -810,7 +840,9 @@ public class FlatStylingSupport
|
|||||||
infos.put( keyPrefix.concat( e.getKey() ), e.getValue() );
|
infos.put( keyPrefix.concat( e.getKey() ), e.getValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getAnnotatedStyleableValue( Object obj, String key ) {
|
public static Object getAnnotatedStyleableValue( Object obj, String key )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
String fieldName = keyToFieldName( key );
|
String fieldName = keyToFieldName( key );
|
||||||
Class<?> cls = obj.getClass();
|
Class<?> cls = obj.getClass();
|
||||||
|
|
||||||
@@ -877,7 +909,9 @@ public class FlatStylingSupport
|
|||||||
extends LinkedHashMap<K,V>
|
extends LinkedHashMap<K,V>
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public V put( K key, V value ) {
|
public V put( K key, V value )
|
||||||
|
throws IllegalArgumentException
|
||||||
|
{
|
||||||
V oldValue = super.put( key, value );
|
V oldValue = super.put( key, value );
|
||||||
if( oldValue != null )
|
if( oldValue != null )
|
||||||
throw new IllegalArgumentException( "duplicate key '" + key + "'" );
|
throw new IllegalArgumentException( "duplicate key '" + key + "'" );
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.event.MouseMotionListener;
|
import java.awt.event.MouseMotionListener;
|
||||||
import java.awt.event.MouseWheelEvent;
|
import java.awt.event.MouseWheelEvent;
|
||||||
|
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.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
@@ -128,12 +129,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
|
||||||
@@ -141,6 +144,11 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TabbedPane.tabHeight int
|
* @uiDefault TabbedPane.tabHeight int
|
||||||
* @uiDefault TabbedPane.tabSelectionHeight int
|
* @uiDefault TabbedPane.tabSelectionHeight int
|
||||||
* @uiDefault TabbedPane.cardTabSelectionHeight int
|
* @uiDefault TabbedPane.cardTabSelectionHeight int
|
||||||
|
* @uiDefault TabbedPane.tabArc int
|
||||||
|
* @uiDefault TabbedPane.tabSelectionArc int
|
||||||
|
* @uiDefault TabbedPane.cardTabArc int
|
||||||
|
* @uiDefault TabbedPane.selectedInsets Insets
|
||||||
|
* @uiDefault TabbedPane.tabSelectionInsets Insets
|
||||||
* @uiDefault TabbedPane.contentSeparatorHeight int
|
* @uiDefault TabbedPane.contentSeparatorHeight int
|
||||||
* @uiDefault TabbedPane.showTabSeparators boolean
|
* @uiDefault TabbedPane.showTabSeparators boolean
|
||||||
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
||||||
@@ -205,7 +213,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;
|
||||||
|
|
||||||
@@ -215,6 +225,11 @@ public class FlatTabbedPaneUI
|
|||||||
@Styleable protected int tabHeight;
|
@Styleable protected int tabHeight;
|
||||||
@Styleable protected int tabSelectionHeight;
|
@Styleable protected int tabSelectionHeight;
|
||||||
/** @since 2 */ @Styleable protected int cardTabSelectionHeight;
|
/** @since 2 */ @Styleable protected int cardTabSelectionHeight;
|
||||||
|
/** @since 3.2 */ @Styleable protected int tabArc;
|
||||||
|
/** @since 3.2 */ @Styleable protected int tabSelectionArc;
|
||||||
|
/** @since 3.2 */ @Styleable protected int cardTabArc;
|
||||||
|
/** @since 3.2 */ @Styleable protected Insets selectedInsets;
|
||||||
|
/** @since 3.2 */ @Styleable protected Insets tabSelectionInsets;
|
||||||
@Styleable protected int contentSeparatorHeight;
|
@Styleable protected int contentSeparatorHeight;
|
||||||
@Styleable protected boolean showTabSeparators;
|
@Styleable protected boolean showTabSeparators;
|
||||||
@Styleable protected boolean tabSeparatorsFullHeight;
|
@Styleable protected boolean tabSeparatorsFullHeight;
|
||||||
@@ -328,7 +343,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" );
|
||||||
|
|
||||||
@@ -338,6 +355,11 @@ public class FlatTabbedPaneUI
|
|||||||
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
||||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||||
cardTabSelectionHeight = UIManager.getInt( "TabbedPane.cardTabSelectionHeight" );
|
cardTabSelectionHeight = UIManager.getInt( "TabbedPane.cardTabSelectionHeight" );
|
||||||
|
tabArc = UIManager.getInt( "TabbedPane.tabArc" );
|
||||||
|
tabSelectionArc = UIManager.getInt( "TabbedPane.tabSelectionArc" );
|
||||||
|
cardTabArc = UIManager.getInt( "TabbedPane.cardTabArc" );
|
||||||
|
selectedInsets = UIManager.getInsets( "TabbedPane.selectedInsets" );
|
||||||
|
tabSelectionInsets = UIManager.getInsets( "TabbedPane.tabSelectionInsets" );
|
||||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||||
@@ -397,7 +419,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,42 +1165,101 @@ 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 )
|
||||||
{
|
{
|
||||||
|
boolean isCard = (getTabType() == TAB_TYPE_CARD);
|
||||||
|
|
||||||
|
// fill whole tab background if tab is rounded or has insets
|
||||||
|
if( (!isCard && tabArc > 0) ||
|
||||||
|
(isCard && cardTabArc > 0) ||
|
||||||
|
(!isCard && selectedInsets != null &&
|
||||||
|
(selectedInsets.top != 0 || selectedInsets.left != 0 ||
|
||||||
|
selectedInsets.bottom != 0 || selectedInsets.right != 0)) )
|
||||||
|
{
|
||||||
|
Color background = tabPane.getBackgroundAt( tabIndex );
|
||||||
|
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||||
|
g.fillRect( x, y, w, h );
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply insets
|
||||||
|
if( !isCard && selectedInsets != null ) {
|
||||||
|
Insets insets = new Insets( 0, 0, 0, 0 );
|
||||||
|
rotateInsets( selectedInsets, insets, tabPane.getTabPlacement() );
|
||||||
|
|
||||||
|
x += scale( insets.left );
|
||||||
|
y += scale( insets.top );
|
||||||
|
w -= scale( insets.left + insets.right );
|
||||||
|
h -= scale( insets.top + insets.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
// paint tab background
|
// paint tab background
|
||||||
Color background = getTabBackground( tabPlacement, tabIndex, isSelected );
|
Color background = getTabBackground( tabPlacement, tabIndex, isSelected );
|
||||||
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||||
g.fillRect( x, y, w, h );
|
if( !isCard && tabArc > 0 ) {
|
||||||
|
float arc = scale( (float) tabArc ) / 2f;
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, w, h, null, arc, arc, arc, arc, 0 );
|
||||||
|
} else if( isCard && cardTabArc > 0 )
|
||||||
|
((Graphics2D)g).fill( createCardTabOuterPath( tabPlacement, x, y, w, h ) );
|
||||||
|
else
|
||||||
|
g.fillRect( x, y, w, h );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @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
|
||||||
@@ -1205,42 +1288,38 @@ public class FlatTabbedPaneUI
|
|||||||
protected void paintCardTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
protected void paintCardTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
||||||
Graphics2D g2 = (Graphics2D) g;
|
Graphics2D g2 = (Graphics2D) g;
|
||||||
|
|
||||||
float borderWidth = scale( (float) contentSeparatorHeight );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( createCardTabOuterPath( tabPlacement, x, y, w, h ), false );
|
||||||
|
path.append( createCardTabInnerPath( tabPlacement, x, y, w, h ), false );
|
||||||
|
|
||||||
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
|
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
|
||||||
|
g2.fill( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
protected Shape createCardTabOuterPath( int tabPlacement, int x, int y, int w, int h ) {
|
||||||
|
float arc = scale( (float) cardTabArc ) / 2f;
|
||||||
|
|
||||||
switch( tabPlacement ) {
|
switch( tabPlacement ) {
|
||||||
default:
|
default:
|
||||||
case TOP:
|
case TOP: return FlatUIUtils.createRoundRectanglePath( x, y, w, h, arc, arc, 0, 0 );
|
||||||
case BOTTOM:
|
case BOTTOM: return FlatUIUtils.createRoundRectanglePath( x, y, w, h, 0, 0, arc, arc );
|
||||||
// paint left and right tab border
|
case LEFT: return FlatUIUtils.createRoundRectanglePath( x, y, w, h, arc, 0, arc, 0 );
|
||||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
case RIGHT: return FlatUIUtils.createRoundRectanglePath( x, y, w, h, 0, arc, 0, arc );
|
||||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
|
||||||
break;
|
|
||||||
case LEFT:
|
|
||||||
case RIGHT:
|
|
||||||
// paint top and bottom tab border
|
|
||||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
|
||||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( cardTabSelectionHeight <= 0 ) {
|
/** @since 3.2 */
|
||||||
// if there is no tab selection indicator, paint a top border as well
|
protected Shape createCardTabInnerPath( int tabPlacement, int x, int y, int w, int h ) {
|
||||||
switch( tabPlacement ) {
|
float bw = scale( (float) contentSeparatorHeight );
|
||||||
default:
|
float arc = (scale( (float) cardTabArc ) / 2f) - bw;
|
||||||
case TOP:
|
|
||||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
switch( tabPlacement ) {
|
||||||
break;
|
default:
|
||||||
case BOTTOM:
|
case TOP: return FlatUIUtils.createRoundRectanglePath( x + bw, y + bw, w - (bw * 2), h - bw, arc, arc, 0, 0 );
|
||||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
case BOTTOM: return FlatUIUtils.createRoundRectanglePath( x + bw, y, w - (bw * 2), h - bw, 0, 0, arc, arc );
|
||||||
break;
|
case LEFT: return FlatUIUtils.createRoundRectanglePath( x + bw, y + bw, w - bw, h - (bw * 2), arc, 0, arc, 0 );
|
||||||
case LEFT:
|
case RIGHT: return FlatUIUtils.createRoundRectanglePath( x, y + bw, w - bw, h - (bw * 2), 0, arc, 0, arc );
|
||||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
|
||||||
break;
|
|
||||||
case RIGHT:
|
|
||||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,38 +1367,62 @@ public class FlatTabbedPaneUI
|
|||||||
? (isTabbedPaneOrChildFocused() ? underlineColor : inactiveUnderlineColor)
|
? (isTabbedPaneOrChildFocused() ? underlineColor : inactiveUnderlineColor)
|
||||||
: disabledUnderlineColor );
|
: disabledUnderlineColor );
|
||||||
|
|
||||||
// paint underline selection
|
boolean isCard = (getTabType() == TAB_TYPE_CARD);
|
||||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
boolean atBottom = !isCard;
|
||||||
Insets contentInsets = atBottom
|
Insets contentInsets = atBottom
|
||||||
? ((!rotateTabRuns && runCount > 1 && !isScrollTabLayout() && getRunForTab( tabPane.getTabCount(), tabIndex ) > 0)
|
? ((!rotateTabRuns && runCount > 1 && !isScrollTabLayout() && getRunForTab( tabPane.getTabCount(), tabIndex ) > 0)
|
||||||
? new Insets( 0, 0, 0, 0 )
|
? new Insets( 0, 0, 0, 0 )
|
||||||
: getContentBorderInsets( tabPlacement ))
|
: getContentBorderInsets( tabPlacement ))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
int tabSelectionHeight = scale( atBottom ? this.tabSelectionHeight : cardTabSelectionHeight );
|
int tabSelectionHeight = scale( isCard ? cardTabSelectionHeight : this.tabSelectionHeight );
|
||||||
int sx, sy;
|
float arc = scale( (float) (isCard ? cardTabArc : tabSelectionArc) ) / 2f;
|
||||||
|
int sx = x, sy = y, sw = w, sh = h;
|
||||||
switch( tabPlacement ) {
|
switch( tabPlacement ) {
|
||||||
case TOP:
|
case TOP:
|
||||||
default:
|
default:
|
||||||
sy = atBottom ? (y + h + contentInsets.top - tabSelectionHeight) : y;
|
sy = atBottom ? (y + h + contentInsets.top - tabSelectionHeight) : y;
|
||||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
sh = tabSelectionHeight;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
sy = atBottom ? (y - contentInsets.bottom) : (y + h - tabSelectionHeight);
|
sy = atBottom ? (y - contentInsets.bottom) : (y + h - tabSelectionHeight);
|
||||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
sh = tabSelectionHeight;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LEFT:
|
case LEFT:
|
||||||
sx = atBottom ? (x + w + contentInsets.left - tabSelectionHeight) : x;
|
sx = atBottom ? (x + w + contentInsets.left - tabSelectionHeight) : x;
|
||||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
sw = tabSelectionHeight;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
sx = atBottom ? (x - contentInsets.right) : (x + w - tabSelectionHeight);
|
sx = atBottom ? (x - contentInsets.right) : (x + w - tabSelectionHeight);
|
||||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
sw = tabSelectionHeight;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply insets
|
||||||
|
if( !isCard && tabSelectionInsets != null ) {
|
||||||
|
Insets insets = new Insets( 0, 0, 0, 0 );
|
||||||
|
rotateInsets( tabSelectionInsets, insets, tabPane.getTabPlacement() );
|
||||||
|
|
||||||
|
sx += scale( insets.left );
|
||||||
|
sy += scale( insets.top );
|
||||||
|
sw -= scale( insets.left + insets.right );
|
||||||
|
sh -= scale( insets.top + insets.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
// paint underline selection
|
||||||
|
if( arc <= 0 )
|
||||||
|
g.fillRect( sx, sy, sw, sh );
|
||||||
|
else {
|
||||||
|
if( isCard ) {
|
||||||
|
Area area = new Area( createCardTabOuterPath( tabPlacement, x, y, w, h ) );
|
||||||
|
area.intersect( new Area( new Rectangle2D.Float( sx, sy, sw, sh ) ) );
|
||||||
|
((Graphics2D)g).fill( area );
|
||||||
|
} else
|
||||||
|
FlatUIUtils.paintSelection( (Graphics2D) g, sx, sy, sw, sh, null, arc, arc, arc, arc, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2.2 */
|
/** @since 2.2 */
|
||||||
@@ -1431,7 +1534,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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1930,7 +2034,7 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
//---- class TabCloseButton -----------------------------------------------
|
//---- class TabCloseButton -----------------------------------------------
|
||||||
|
|
||||||
private class TabCloseButton
|
private static class TabCloseButton
|
||||||
extends JButton
|
extends JButton
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
@@ -1940,7 +2044,7 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
//---- class ContainerUIResource ------------------------------------------
|
//---- class ContainerUIResource ------------------------------------------
|
||||||
|
|
||||||
private class ContainerUIResource
|
private static class ContainerUIResource
|
||||||
extends JPanel
|
extends JPanel
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
@@ -2345,7 +2449,7 @@ public class FlatTabbedPaneUI
|
|||||||
if( isPreciseWheel &&
|
if( isPreciseWheel &&
|
||||||
getScrollButtonsPlacement() == BOTH &&
|
getScrollButtonsPlacement() == BOTH &&
|
||||||
getScrollButtonsPolicy() == AS_NEEDED_SINGLE &&
|
getScrollButtonsPolicy() == AS_NEEDED_SINGLE &&
|
||||||
(isLeftToRight() || !horizontal) || // scroll buttons are hidden in right-to-left
|
(isLeftToRight() || !horizontal) && // scroll buttons are hidden in right-to-left
|
||||||
scrollBackwardButtonPrefSize != null )
|
scrollBackwardButtonPrefSize != null )
|
||||||
{
|
{
|
||||||
// special cases for scrolling with touchpad or high-resolution wheel:
|
// special cases for scrolling with touchpad or high-resolution wheel:
|
||||||
@@ -3014,7 +3118,7 @@ public class FlatTabbedPaneUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CENTER:
|
case CENTER:
|
||||||
shiftTabs( 0, (diff) / 2 );
|
shiftTabs( 0, diff / 2 );
|
||||||
topHeight += diff / 2;
|
topHeight += diff / 2;
|
||||||
bottomHeight += diff - (diff / 2);
|
bottomHeight += diff - (diff / 2);
|
||||||
break;
|
break;
|
||||||
@@ -3463,7 +3567,7 @@ public class FlatTabbedPaneUI
|
|||||||
//---- class FlatSelectedTabRepainter -------------------------------------
|
//---- class FlatSelectedTabRepainter -------------------------------------
|
||||||
|
|
||||||
private static class FlatSelectedTabRepainter
|
private static class FlatSelectedTabRepainter
|
||||||
implements PropertyChangeListener//, Runnable
|
implements PropertyChangeListener
|
||||||
{
|
{
|
||||||
private static FlatSelectedTabRepainter instance;
|
private static FlatSelectedTabRepainter instance;
|
||||||
|
|
||||||
@@ -3513,17 +3617,31 @@ public class FlatTabbedPaneUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "activeWindow":
|
case "activeWindow":
|
||||||
repaintSelectedTabs( keyboardFocusManager.getPermanentFocusOwner() );
|
Component permanentFocusOwner = keyboardFocusManager.getPermanentFocusOwner();
|
||||||
|
if( permanentFocusOwner != null )
|
||||||
|
repaintSelectedTabs( permanentFocusOwner );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void repaintSelectedTabs( Component c ) {
|
private void repaintSelectedTabs( Component c ) {
|
||||||
if( c instanceof JTabbedPane )
|
// Use invokeLater because this method may be invoked while UI update
|
||||||
repaintSelectedTab( (JTabbedPane) c );
|
// is in progress. This may happen if a focusable component (e.g. text field)
|
||||||
|
// is used as tab component (see JTabbedPane.setTabComponentAt()).
|
||||||
|
// uninstallTabContainer() removes all components from tabbed pane and
|
||||||
|
// the text field looses focus.
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
// because this is invoked later, check whether component is still displayable
|
||||||
|
if( !c.isDisplayable() )
|
||||||
|
return;
|
||||||
|
|
||||||
while( (c = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c )) != null )
|
if( c instanceof JTabbedPane )
|
||||||
repaintSelectedTab( (JTabbedPane) c );
|
repaintSelectedTab( (JTabbedPane) c );
|
||||||
|
|
||||||
|
Component c2 = c;
|
||||||
|
while( (c2 = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c2 )) != null )
|
||||||
|
repaintSelectedTab( (JTabbedPane) c2 );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void repaintSelectedTab( JTabbedPane tabbedPane ) {
|
private void repaintSelectedTab( JTabbedPane tabbedPane ) {
|
||||||
|
|||||||
@@ -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,28 +172,57 @@ 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();
|
||||||
int columnCount = table.getColumnCount();
|
boolean columnSelectionAllowed = table.getColumnSelectionAllowed();
|
||||||
int[] selectedRows = table.getSelectedRows();
|
|
||||||
for( int selectedRow : selectedRows ) {
|
|
||||||
for( int column = 0; column < columnCount; column++ ) {
|
|
||||||
if( table.isCellEditable( selectedRow, column ) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( 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();
|
||||||
|
if( columnCount > maxCheckCellsEditable )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check whether at least one selected cell is editable
|
||||||
|
int selectedRow = table.getSelectedRow();
|
||||||
|
for( int column = 0; column < columnCount; column++ ) {
|
||||||
|
if( table.isCellEditable( selectedRow, column ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if( columnSelectionAllowed ) {
|
||||||
|
// column selection mode
|
||||||
|
|
||||||
|
// 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;
|
||||||
for( int row = 0; row < rowCount; row++ ) {
|
|
||||||
if( table.isCellEditable( row, selectedColumn ) )
|
// check whether at least one selected cell is editable
|
||||||
return true;
|
int selectedColumn = table.getSelectedColumn();
|
||||||
}
|
for( int row = 0; row < rowCount; row++ ) {
|
||||||
|
if( table.isCellEditable( row, selectedColumn ) )
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -277,6 +277,9 @@ public class FlatTableUI
|
|||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected Object applyStyleProperty( String key, Object value ) {
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
if( "rowHeight".equals( key ) && value instanceof Integer )
|
||||||
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, table, key, value );
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, table, key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatTextAreaUI -->
|
* <!-- FlatTextAreaUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault TextArea.disabledBackground Color used if not enabled
|
* @uiDefault TextArea.disabledBackground Color used if not enabled
|
||||||
* @uiDefault TextArea.inactiveBackground Color used if not editable
|
* @uiDefault TextArea.inactiveBackground Color used if not editable
|
||||||
* @uiDefault TextArea.focusedBackground Color optional
|
* @uiDefault TextArea.focusedBackground Color optional
|
||||||
@@ -66,7 +65,6 @@ public class FlatTextAreaUI
|
|||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
@Styleable protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
private Color background;
|
private Color background;
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color inactiveBackground;
|
@Styleable protected Color inactiveBackground;
|
||||||
@@ -103,7 +101,6 @@ public class FlatTextAreaUI
|
|||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
background = UIManager.getColor( "TextArea.background" );
|
background = UIManager.getColor( "TextArea.background" );
|
||||||
disabledBackground = UIManager.getColor( "TextArea.disabledBackground" );
|
disabledBackground = UIManager.getColor( "TextArea.disabledBackground" );
|
||||||
inactiveBackground = UIManager.getColor( "TextArea.inactiveBackground" );
|
inactiveBackground = UIManager.getColor( "TextArea.inactiveBackground" );
|
||||||
@@ -227,6 +224,6 @@ public class FlatTextAreaUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
FlatEditorPaneUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
FlatEditorPaneUI.paintBackground( g, getComponent(), focusedBackground );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import javax.swing.JTextField;
|
|||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
@@ -81,7 +82,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatTextFieldUI -->
|
* <!-- FlatTextFieldUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault TextField.placeholderForeground Color
|
* @uiDefault TextField.placeholderForeground Color
|
||||||
* @uiDefault TextField.focusedBackground Color optional
|
* @uiDefault TextField.focusedBackground Color optional
|
||||||
* @uiDefault TextField.iconTextGap int optional, default is 4
|
* @uiDefault TextField.iconTextGap int optional, default is 4
|
||||||
@@ -95,7 +95,6 @@ public class FlatTextFieldUI
|
|||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
@Styleable protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
private Color background;
|
private Color background;
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color inactiveBackground;
|
@Styleable protected Color inactiveBackground;
|
||||||
@@ -165,7 +164,6 @@ public class FlatTextFieldUI
|
|||||||
|
|
||||||
String prefix = getPropertyPrefix();
|
String prefix = getPropertyPrefix();
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
background = UIManager.getColor( prefix + ".background" );
|
background = UIManager.getColor( prefix + ".background" );
|
||||||
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
||||||
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
||||||
@@ -402,7 +400,7 @@ public class FlatTextFieldUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintSafely( Graphics g ) {
|
protected void paintSafely( Graphics g ) {
|
||||||
paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
paintBackground( g, getComponent(), focusedBackground );
|
||||||
paintPlaceholder( g );
|
paintPlaceholder( g );
|
||||||
|
|
||||||
if( hasLeadingIcon() || hasTrailingIcon() )
|
if( hasLeadingIcon() || hasTrailingIcon() )
|
||||||
@@ -422,7 +420,7 @@ debug*/
|
|||||||
// background is painted elsewhere
|
// background is painted elsewhere
|
||||||
}
|
}
|
||||||
|
|
||||||
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
|
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||||
// do not paint background if:
|
// do not paint background if:
|
||||||
// - not opaque and
|
// - not opaque and
|
||||||
// - border is not a flat border and
|
// - border is not a flat border and
|
||||||
@@ -443,14 +441,14 @@ debug*/
|
|||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
g2.setColor( getBackground( c, isIntelliJTheme, focusedBackground ) );
|
g2.setColor( getBackground( c, focusedBackground ) );
|
||||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color getBackground( JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
|
static Color getBackground( JTextComponent c, Color focusedBackground ) {
|
||||||
Color background = c.getBackground();
|
Color background = c.getBackground();
|
||||||
|
|
||||||
// always use explicitly set color
|
// always use explicitly set color
|
||||||
@@ -461,10 +459,6 @@ debug*/
|
|||||||
if( focusedBackground != null && FlatUIUtils.isPermanentFocusOwner( c ) )
|
if( focusedBackground != null && FlatUIUtils.isPermanentFocusOwner( c ) )
|
||||||
return focusedBackground;
|
return focusedBackground;
|
||||||
|
|
||||||
// for compatibility with IntelliJ themes
|
|
||||||
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) )
|
|
||||||
return FlatUIUtils.getParentBackground( c );
|
|
||||||
|
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,10 +481,22 @@ debug*/
|
|||||||
// compute placeholder location
|
// compute placeholder location
|
||||||
Rectangle r = getVisibleEditorRect();
|
Rectangle r = getVisibleEditorRect();
|
||||||
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
||||||
String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width );
|
int x = r.x;
|
||||||
int x = r.x + (isLeftToRight() ? 0 : r.width - fm.stringWidth( clippedPlaceholder ));
|
|
||||||
int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2);
|
int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2);
|
||||||
|
|
||||||
|
// apply horizontal alignment to x location
|
||||||
|
String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width );
|
||||||
|
int stringWidth = fm.stringWidth( clippedPlaceholder );
|
||||||
|
int halign = (c instanceof JTextField) ? ((JTextField)c).getHorizontalAlignment() : SwingConstants.LEADING;
|
||||||
|
if( halign == SwingConstants.LEADING )
|
||||||
|
halign = isLeftToRight() ? SwingConstants.LEFT : SwingConstants.RIGHT;
|
||||||
|
else if( halign == SwingConstants.TRAILING )
|
||||||
|
halign = isLeftToRight() ? SwingConstants.RIGHT : SwingConstants.LEFT;
|
||||||
|
if( halign == SwingConstants.RIGHT )
|
||||||
|
x += r.width - stringWidth;
|
||||||
|
else if( halign == SwingConstants.CENTER )
|
||||||
|
x = Math.max( 0, x + (r.width / 2) - (stringWidth / 2) );
|
||||||
|
|
||||||
// paint placeholder
|
// paint placeholder
|
||||||
g.setColor( placeholderForeground );
|
g.setColor( placeholderForeground );
|
||||||
FlatUIUtils.drawString( c, g, clippedPlaceholder, x, y );
|
FlatUIUtils.drawString( c, g, clippedPlaceholder, x, y );
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatTextPaneUI -->
|
* <!-- FlatTextPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault TextPane.focusedBackground Color optional
|
* @uiDefault TextPane.focusedBackground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -66,7 +65,6 @@ public class FlatTextPaneUI
|
|||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
@Styleable protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
|
||||||
private Color background;
|
private Color background;
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color inactiveBackground;
|
@Styleable protected Color inactiveBackground;
|
||||||
@@ -98,7 +96,6 @@ public class FlatTextPaneUI
|
|||||||
|
|
||||||
String prefix = getPropertyPrefix();
|
String prefix = getPropertyPrefix();
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
|
||||||
background = UIManager.getColor( prefix + ".background" );
|
background = UIManager.getColor( prefix + ".background" );
|
||||||
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
||||||
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
||||||
@@ -220,6 +217,6 @@ public class FlatTextPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
FlatEditorPaneUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
FlatEditorPaneUI.paintBackground( g, getComponent(), focusedBackground );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import javax.swing.Icon;
|
|||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JInternalFrame;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@@ -96,6 +97,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
||||||
* @uiDefault TitlePane.showIconBesideTitle boolean
|
* @uiDefault TitlePane.showIconBesideTitle boolean
|
||||||
* @uiDefault TitlePane.menuBarTitleGap int
|
* @uiDefault TitlePane.menuBarTitleGap int
|
||||||
|
* @uiDefault TitlePane.menuBarTitleMinimumGap int
|
||||||
* @uiDefault TitlePane.menuBarResizeHeight int
|
* @uiDefault TitlePane.menuBarResizeHeight int
|
||||||
* @uiDefault TitlePane.closeIcon Icon
|
* @uiDefault TitlePane.closeIcon Icon
|
||||||
* @uiDefault TitlePane.iconifyIcon Icon
|
* @uiDefault TitlePane.iconifyIcon Icon
|
||||||
@@ -109,29 +111,30 @@ public class FlatTitlePane
|
|||||||
{
|
{
|
||||||
private static final String KEY_DEBUG_SHOW_RECTANGLES = "FlatLaf.debug.titlebar.showRectangles";
|
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;
|
||||||
protected final Color activeBackground = UIManager.getColor( "TitlePane.background" );
|
protected final Color activeBackground;
|
||||||
protected final Color inactiveBackground = UIManager.getColor( "TitlePane.inactiveBackground" );
|
protected final Color inactiveBackground;
|
||||||
protected final Color activeForeground = UIManager.getColor( "TitlePane.foreground" );
|
protected final Color activeForeground;
|
||||||
protected final Color inactiveForeground = UIManager.getColor( "TitlePane.inactiveForeground" );
|
protected final Color inactiveForeground;
|
||||||
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
protected final Color embeddedForeground;
|
||||||
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
protected final Color borderColor;
|
||||||
|
|
||||||
/** @since 2 */ protected final boolean showIcon = FlatUIUtils.getUIBoolean( "TitlePane.showIcon", true );
|
/** @since 2 */ protected final boolean showIcon;
|
||||||
/** @since 2.5 */ protected final boolean showIconInDialogs = FlatUIUtils.getUIBoolean( "TitlePane.showIconInDialogs", true );
|
/** @since 2.5 */ protected final boolean showIconInDialogs;
|
||||||
/** @since 2 */ protected final int noIconLeftGap = FlatUIUtils.getUIInt( "TitlePane.noIconLeftGap", 8 );
|
/** @since 2 */ protected final int noIconLeftGap;
|
||||||
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
protected final Dimension iconSize;
|
||||||
/** @since 2.4 */ protected final int titleMinimumWidth = FlatUIUtils.getUIInt( "TitlePane.titleMinimumWidth", 60 );
|
/** @since 2.4 */ protected final int titleMinimumWidth;
|
||||||
/** @since 2.4 */ protected final int buttonMinimumWidth = FlatUIUtils.getUIInt( "TitlePane.buttonMinimumWidth", 30 );
|
/** @since 2.4 */ protected final int buttonMinimumWidth;
|
||||||
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
|
protected final int buttonMaximizedHeight;
|
||||||
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
|
protected final boolean centerTitle;
|
||||||
protected final boolean centerTitleIfMenuBarEmbedded = FlatUIUtils.getUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", true );
|
protected final boolean centerTitleIfMenuBarEmbedded;
|
||||||
/** @since 2.4 */ protected final boolean showIconBesideTitle = UIManager.getBoolean( "TitlePane.showIconBesideTitle" );
|
/** @since 2.4 */ protected final boolean showIconBesideTitle;
|
||||||
protected final int menuBarTitleGap = FlatUIUtils.getUIInt( "TitlePane.menuBarTitleGap", 40 );
|
protected final int menuBarTitleGap;
|
||||||
/** @since 2.4 */ protected final int menuBarTitleMinimumGap = FlatUIUtils.getUIInt( "TitlePane.menuBarTitleMinimumGap", 12 );
|
/** @since 2.4 */ protected final int menuBarTitleMinimumGap;
|
||||||
/** @since 2.4 */ protected final int menuBarResizeHeight = FlatUIUtils.getUIInt( "TitlePane.menuBarResizeHeight", 4 );
|
/** @since 2.4 */ protected final int menuBarResizeHeight;
|
||||||
|
|
||||||
protected final JRootPane rootPane;
|
protected final JRootPane rootPane;
|
||||||
|
protected final String windowStyle;
|
||||||
|
|
||||||
protected JPanel leftPanel;
|
protected JPanel leftPanel;
|
||||||
protected JLabel iconLabel;
|
protected JLabel iconLabel;
|
||||||
@@ -150,6 +153,34 @@ public class FlatTitlePane
|
|||||||
public FlatTitlePane( JRootPane rootPane ) {
|
public FlatTitlePane( JRootPane rootPane ) {
|
||||||
this.rootPane = rootPane;
|
this.rootPane = rootPane;
|
||||||
|
|
||||||
|
Window w = SwingUtilities.getWindowAncestor( rootPane );
|
||||||
|
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
|
||||||
|
windowStyle = clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
|
||||||
|
|
||||||
|
titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle );
|
||||||
|
activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle );
|
||||||
|
inactiveBackground = FlatUIUtils.getSubUIColor( "TitlePane.inactiveBackground", windowStyle );
|
||||||
|
activeForeground = FlatUIUtils.getSubUIColor( "TitlePane.foreground", windowStyle );
|
||||||
|
inactiveForeground = FlatUIUtils.getSubUIColor( "TitlePane.inactiveForeground", windowStyle );
|
||||||
|
embeddedForeground = FlatUIUtils.getSubUIColor( "TitlePane.embeddedForeground", windowStyle );
|
||||||
|
// not using windowStyle here because TitlePane.borderColor is also used in FlatRootPaneUI
|
||||||
|
borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
||||||
|
|
||||||
|
showIcon = FlatUIUtils.getSubUIBoolean( "TitlePane.showIcon", windowStyle, true );
|
||||||
|
showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true );
|
||||||
|
noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 );
|
||||||
|
iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle );
|
||||||
|
titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 );
|
||||||
|
buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 );
|
||||||
|
buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 );
|
||||||
|
centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false );
|
||||||
|
centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true );
|
||||||
|
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
|
||||||
|
menuBarTitleGap = FlatUIUtils.getSubUIInt( "TitlePane.menuBarTitleGap", windowStyle, 40 );
|
||||||
|
menuBarTitleMinimumGap = FlatUIUtils.getSubUIInt( "TitlePane.menuBarTitleMinimumGap", windowStyle, 12 );
|
||||||
|
menuBarResizeHeight = FlatUIUtils.getSubUIInt( "TitlePane.menuBarResizeHeight", windowStyle, 4 );
|
||||||
|
|
||||||
|
|
||||||
handler = createHandler();
|
handler = createHandler();
|
||||||
setBorder( createTitlePaneBorder() );
|
setBorder( createTitlePaneBorder() );
|
||||||
|
|
||||||
@@ -182,8 +213,8 @@ public class FlatTitlePane
|
|||||||
setUI( new FlatTitleLabelUI() );
|
setUI( new FlatTitleLabelUI() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
iconLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.iconMargins" ) ) );
|
iconLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle ) ) );
|
||||||
titleLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.titleMargins" ) ) );
|
titleLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle ) ) );
|
||||||
|
|
||||||
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
||||||
leftPanel.setOpaque( false );
|
leftPanel.setOpaque( false );
|
||||||
@@ -310,7 +341,7 @@ public class FlatTitlePane
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected JButton createButton( String iconKey, String accessibleName, ActionListener action ) {
|
protected JButton createButton( String iconKey, String accessibleName, ActionListener action ) {
|
||||||
JButton button = new JButton( UIManager.getIcon( iconKey ) ) {
|
JButton button = new JButton( FlatUIUtils.getSubUIIcon( iconKey, windowStyle ) ) {
|
||||||
@Override
|
@Override
|
||||||
public Dimension getMinimumSize() {
|
public Dimension getMinimumSize() {
|
||||||
// allow the button to shrink if space is rare
|
// allow the button to shrink if space is rare
|
||||||
@@ -360,9 +391,8 @@ public class FlatTitlePane
|
|||||||
|
|
||||||
if( window instanceof Frame ) {
|
if( window instanceof Frame ) {
|
||||||
Frame frame = (Frame) window;
|
Frame frame = (Frame) window;
|
||||||
boolean maximized = ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0);
|
|
||||||
|
|
||||||
if( maximized &&
|
if( isWindowMaximized() &&
|
||||||
!(SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window )) &&
|
!(SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window )) &&
|
||||||
rootPane.getClientProperty( "_flatlaf.maximizedBoundsUpToDate" ) == null )
|
rootPane.getClientProperty( "_flatlaf.maximizedBoundsUpToDate" ) == null )
|
||||||
{
|
{
|
||||||
@@ -393,7 +423,7 @@ public class FlatTitlePane
|
|||||||
if( window instanceof Frame ) {
|
if( window instanceof Frame ) {
|
||||||
Frame frame = (Frame) window;
|
Frame frame = (Frame) window;
|
||||||
boolean maximizable = frame.isResizable() && clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_MAXIMIZE, true );
|
boolean maximizable = frame.isResizable() && clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_MAXIMIZE, true );
|
||||||
boolean maximized = ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0);
|
boolean maximized = isWindowMaximized();
|
||||||
|
|
||||||
iconifyButton.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICONIFFY, true ) );
|
iconifyButton.setVisible( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICONIFFY, true ) );
|
||||||
maximizeButton.setVisible( maximizable && !maximized );
|
maximizeButton.setVisible( maximizable && !maximized );
|
||||||
@@ -643,7 +673,10 @@ public class FlatTitlePane
|
|||||||
|
|
||||||
/** @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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -661,8 +694,30 @@ public class FlatTitlePane
|
|||||||
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() {
|
||||||
@@ -766,8 +821,7 @@ public class FlatTitlePane
|
|||||||
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();
|
||||||
@@ -929,6 +983,13 @@ public class FlatTitlePane
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow internal frames in layered pane to be moved/resized when placed over title bar
|
||||||
|
for( Component c : rootPane.getLayeredPane().getComponents() ) {
|
||||||
|
r = (c instanceof JInternalFrame) ? getNativeHitTestSpot( (JInternalFrame) c ) : null;
|
||||||
|
if( r != null )
|
||||||
|
hitTestSpots.add( r );
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle minimizeButtonBounds = boundsInWindow( iconifyButton );
|
Rectangle minimizeButtonBounds = boundsInWindow( iconifyButton );
|
||||||
Rectangle maximizeButtonBounds = boundsInWindow( maximizeButton.isVisible() ? maximizeButton : restoreButton );
|
Rectangle maximizeButtonBounds = boundsInWindow( maximizeButton.isVisible() ? maximizeButton : restoreButton );
|
||||||
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
||||||
@@ -1188,6 +1249,13 @@ public class FlatTitlePane
|
|||||||
|
|
||||||
@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();
|
||||||
}
|
}
|
||||||
@@ -1195,7 +1263,7 @@ public class FlatTitlePane
|
|||||||
//---- interface MouseListener ----
|
//---- interface MouseListener ----
|
||||||
|
|
||||||
private Point dragOffset;
|
private Point dragOffset;
|
||||||
private boolean nativeMove;
|
private boolean linuxNativeMove;
|
||||||
private long lastSingleClickWhen;
|
private long lastSingleClickWhen;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1203,7 +1271,7 @@ public class FlatTitlePane
|
|||||||
// 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;
|
||||||
@@ -1241,7 +1309,7 @@ public class FlatTitlePane
|
|||||||
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 ) ) {
|
||||||
@@ -1261,7 +1329,7 @@ public class FlatTitlePane
|
|||||||
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;
|
||||||
|
|
||||||
@@ -1291,7 +1359,7 @@ public class FlatTitlePane
|
|||||||
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 ) )
|
||||||
|
|||||||
@@ -39,10 +39,12 @@ import javax.swing.JComboBox;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LayoutFocusTraversalPolicy;
|
import javax.swing.LayoutFocusTraversalPolicy;
|
||||||
|
import javax.swing.RootPaneContainer;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicToolBarUI;
|
import javax.swing.plaf.basic.BasicToolBarUI;
|
||||||
|
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;
|
||||||
@@ -156,6 +158,13 @@ public class FlatToolBarUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RootPaneContainer createFloatingWindow( JToolBar toolbar ) {
|
||||||
|
RootPaneContainer floatingWindow = super.createFloatingWindow( toolbar );
|
||||||
|
floatingWindow.getRootPane().putClientProperty( FlatClientProperties.WINDOW_STYLE, FlatClientProperties.WINDOW_STYLE_SMALL );
|
||||||
|
return floatingWindow;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ContainerListener createToolBarContListener() {
|
protected ContainerListener createToolBarContListener() {
|
||||||
return new ToolBarContListener() {
|
return new ToolBarContListener() {
|
||||||
|
|||||||
@@ -158,6 +158,10 @@ 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 boolean paintLines;
|
||||||
private Color defaultCellNonSelectionBackground;
|
private Color defaultCellNonSelectionBackground;
|
||||||
private Color defaultSelectionBackground;
|
private Color defaultSelectionBackground;
|
||||||
@@ -193,6 +197,10 @@ public class FlatTreeUI
|
|||||||
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
|
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
|
||||||
showDefaultIcons = UIManager.getBoolean( "Tree.showDefaultIcons" );
|
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" );
|
paintLines = UIManager.getBoolean( "Tree.paintLines" );
|
||||||
defaultCellNonSelectionBackground = UIManager.getColor( "Tree.textBackground" );
|
defaultCellNonSelectionBackground = UIManager.getColor( "Tree.textBackground" );
|
||||||
defaultSelectionBackground = selectionBackground;
|
defaultSelectionBackground = selectionBackground;
|
||||||
@@ -219,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;
|
||||||
@@ -233,9 +245,14 @@ public class FlatTreeUI
|
|||||||
// remove default leaf/closed/opened icons
|
// remove default leaf/closed/opened icons
|
||||||
if( !showDefaultIcons && currentCellRenderer instanceof DefaultTreeCellRenderer ) {
|
if( !showDefaultIcons && currentCellRenderer instanceof DefaultTreeCellRenderer ) {
|
||||||
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) currentCellRenderer;
|
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) currentCellRenderer;
|
||||||
renderer.setLeafIcon( null );
|
if( renderer.getLeafIcon() == defaultLeafIcon &&
|
||||||
renderer.setClosedIcon( null );
|
renderer.getClosedIcon() == defaultClosedIcon &&
|
||||||
renderer.setOpenIcon( null );
|
renderer.getOpenIcon() == defaultOpenIcon )
|
||||||
|
{
|
||||||
|
renderer.setLeafIcon( null );
|
||||||
|
renderer.setClosedIcon( null );
|
||||||
|
renderer.setOpenIcon( null );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -388,6 +420,9 @@ public class FlatTreeUI
|
|||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected Object applyStyleProperty( String key, Object value ) {
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
if( "rowHeight".equals( key ) && value instanceof Integer )
|
||||||
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, tree, key, value );
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, tree, key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,7 +578,7 @@ public class FlatTreeUI
|
|||||||
if( isSelected && isWideSelection() ) {
|
if( isSelected && isWideSelection() ) {
|
||||||
Color oldColor = g.getColor();
|
Color oldColor = g.getColor();
|
||||||
g.setColor( selectionInactiveBackground );
|
g.setColor( selectionInactiveBackground );
|
||||||
paintWideSelection( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
paintWideSelection( g, bounds, row );
|
||||||
g.setColor( oldColor );
|
g.setColor( oldColor );
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -601,7 +636,7 @@ public class FlatTreeUI
|
|||||||
|
|
||||||
if( isWideSelection() ) {
|
if( isWideSelection() ) {
|
||||||
// wide selection
|
// wide selection
|
||||||
paintWideSelection( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf );
|
paintWideSelection( g, bounds, row );
|
||||||
} else {
|
} else {
|
||||||
// non-wide selection
|
// non-wide selection
|
||||||
paintCellBackground( g, rendererComponent, bounds, row, true );
|
paintCellBackground( g, rendererComponent, bounds, row, true );
|
||||||
@@ -670,9 +705,7 @@ public class FlatTreeUI
|
|||||||
return oldColor;
|
return oldColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void paintWideSelection( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds,
|
private void paintWideSelection( Graphics g, Rectangle bounds, int row ) {
|
||||||
TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
|
|
||||||
{
|
|
||||||
float arcTop, arcBottom;
|
float arcTop, arcBottom;
|
||||||
arcTop = arcBottom = UIScale.scale( selectionArc / 2f );
|
arcTop = arcBottom = UIScale.scale( selectionArc / 2f );
|
||||||
|
|
||||||
@@ -695,7 +728,7 @@ public class FlatTreeUI
|
|||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import java.util.IdentityHashMap;
|
|||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
@@ -166,6 +167,88 @@ public class FlatUIUtils
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static Color getSubUIColor( String key, String subKey ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Color value = UIManager.getColor( buildSubKey( key, subKey ) );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return UIManager.getColor( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static boolean getSubUIBoolean( String key, String subKey, boolean defaultValue ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Object value = UIManager.get( buildSubKey( key, subKey ) );
|
||||||
|
if( value instanceof Boolean )
|
||||||
|
return (Boolean) value;
|
||||||
|
}
|
||||||
|
return getUIBoolean( key, defaultValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static int getSubUIInt( String key, String subKey, int defaultValue ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Object value = UIManager.get( buildSubKey( key, subKey ) );
|
||||||
|
if( value instanceof Integer )
|
||||||
|
return (Integer) value;
|
||||||
|
}
|
||||||
|
return getUIInt( key, defaultValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static Insets getSubUIInsets( String key, String subKey ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Insets value = UIManager.getInsets( buildSubKey( key, subKey ) );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return UIManager.getInsets( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static Dimension getSubUIDimension( String key, String subKey ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Dimension value = UIManager.getDimension( buildSubKey( key, subKey ) );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return UIManager.getDimension( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static Icon getSubUIIcon( String key, String subKey ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Icon value = UIManager.getIcon( buildSubKey( key, subKey ) );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return UIManager.getIcon( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public static Font getSubUIFont( String key, String subKey ) {
|
||||||
|
if( subKey != null ) {
|
||||||
|
Font value = UIManager.getFont( buildSubKey( key, subKey ) );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return UIManager.getFont( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts {@code subKey} at last dot in {@code key}.
|
||||||
|
* <p>
|
||||||
|
* E.g. {@code buildSubKey( "TitlePane.font", "small" )} returns {@code "TitlePane.small.font"}.
|
||||||
|
*/
|
||||||
|
private static String buildSubKey( String key, String subKey ) {
|
||||||
|
int dot = key.lastIndexOf( '.' );
|
||||||
|
return (dot >= 0)
|
||||||
|
? key.substring( 0, dot ) + '.' + subKey + '.' + key.substring( dot + 1 )
|
||||||
|
: key;
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 1.1.2 */
|
/** @since 1.1.2 */
|
||||||
public static boolean getBoolean( JComponent c, String systemPropertyKey,
|
public static boolean getBoolean( JComponent c, String systemPropertyKey,
|
||||||
String clientPropertyKey, String uiKey, boolean defaultValue )
|
String clientPropertyKey, String uiKey, boolean defaultValue )
|
||||||
@@ -200,6 +283,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 );
|
||||||
}
|
}
|
||||||
@@ -721,7 +808,7 @@ public class FlatUIUtils
|
|||||||
{
|
{
|
||||||
dotSize = UIScale.scale( dotSize );
|
dotSize = UIScale.scale( dotSize );
|
||||||
gap = UIScale.scale( gap );
|
gap = UIScale.scale( gap );
|
||||||
int gripSize = (dotSize * dotCount) + ((gap * (dotCount - 1)));
|
int gripSize = (dotSize * dotCount) + (gap * (dotCount - 1));
|
||||||
|
|
||||||
// calculate grip position
|
// calculate grip position
|
||||||
float gx;
|
float gx;
|
||||||
|
|||||||
@@ -88,10 +88,6 @@ class FlatWindowsNativeWindowBorder
|
|||||||
if( !SystemInfo.isWindows_10_orLater )
|
if( !SystemInfo.isWindows_10_orLater )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// requires x86 architecture
|
|
||||||
if( !SystemInfo.isX86 && !SystemInfo.isX86_64 )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// check whether native library was successfully loaded
|
// check whether native library was successfully loaded
|
||||||
if( !FlatNativeLibrary.isLoaded() )
|
if( !FlatNativeLibrary.isLoaded() )
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import java.awt.Paint;
|
|||||||
import java.awt.Polygon;
|
import java.awt.Polygon;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.RenderingHints.Key;
|
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.Stroke;
|
import java.awt.Stroke;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
@@ -368,12 +367,12 @@ public class Graphics2DProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRenderingHint( Key hintKey, Object hintValue ) {
|
public void setRenderingHint( RenderingHints.Key hintKey, Object hintValue ) {
|
||||||
delegate.setRenderingHint( hintKey, hintValue );
|
delegate.setRenderingHint( hintKey, hintValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getRenderingHint( Key hintKey ) {
|
public Object getRenderingHint( RenderingHints.Key hintKey ) {
|
||||||
return delegate.getRenderingHint( hintKey );
|
return delegate.getRenderingHint( hintKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,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 );
|
||||||
@@ -94,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 );
|
||||||
@@ -106,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;
|
||||||
|
|||||||
@@ -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 ) {
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.image.AbstractMultiResolutionImage;
|
import java.awt.image.AbstractMultiResolutionImage;
|
||||||
import java.awt.image.BaseMultiResolutionImage;
|
import java.awt.image.BaseMultiResolutionImage;
|
||||||
|
import java.awt.image.ImageObserver;
|
||||||
|
import java.awt.image.ImageProducer;
|
||||||
import java.awt.image.MultiResolutionImage;
|
import java.awt.image.MultiResolutionImage;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -116,6 +119,26 @@ public class MultiResolutionImageSupport
|
|||||||
return mapAndCacheImage( mrImage );
|
return mapAndCacheImage( mrImage );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth( ImageObserver observer ) {
|
||||||
|
return mrImage.getWidth( observer );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight( ImageObserver observer ) {
|
||||||
|
return mrImage.getHeight( observer );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageProducer getSource() {
|
||||||
|
return mrImage.getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getProperty( String name, ImageObserver observer ) {
|
||||||
|
return mrImage.getProperty( name, observer );
|
||||||
|
}
|
||||||
|
|
||||||
private Image mapAndCacheImage( Image image ) {
|
private Image mapAndCacheImage( Image image ) {
|
||||||
return cache.computeIfAbsent( image, img -> {
|
return cache.computeIfAbsent( image, img -> {
|
||||||
// using ImageIcon here makes sure that the image is loaded
|
// using ImageIcon here makes sure that the image is loaded
|
||||||
@@ -134,7 +157,7 @@ public class MultiResolutionImageSupport
|
|||||||
{
|
{
|
||||||
private final Dimension[] dimensions;
|
private final Dimension[] dimensions;
|
||||||
private final Function<Dimension, Image> producer;
|
private final Function<Dimension, Image> producer;
|
||||||
private final IdentityHashMap<Dimension, Image> cache = new IdentityHashMap<>();
|
private final HashMap<Dimension, Image> cache = new HashMap<>();
|
||||||
|
|
||||||
ProducerMultiResolutionImage( Dimension[] dimensions, Function<Dimension, Image> producer ) {
|
ProducerMultiResolutionImage( Dimension[] dimensions, Function<Dimension, Image> producer ) {
|
||||||
this.dimensions = dimensions;
|
this.dimensions = dimensions;
|
||||||
@@ -159,6 +182,16 @@ public class MultiResolutionImageSupport
|
|||||||
return produceAndCacheImage( dimensions[0] );
|
return produceAndCacheImage( dimensions[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth( ImageObserver observer ) {
|
||||||
|
return dimensions[0].width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight( ImageObserver observer ) {
|
||||||
|
return dimensions[0].height;
|
||||||
|
}
|
||||||
|
|
||||||
private Image produceAndCacheImage( Dimension size ) {
|
private Image produceAndCacheImage( Dimension size ) {
|
||||||
return cache.computeIfAbsent( size, size2 -> {
|
return cache.computeIfAbsent( size, size2 -> {
|
||||||
// using ImageIcon here makes sure that the image is loaded
|
// using ImageIcon here makes sure that the image is loaded
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
module com.formdev.flatlaf {
|
module com.formdev.flatlaf {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
@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)
|
||||||
@@ -331,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
|
||||||
|
|
||||||
|
|||||||
@@ -288,6 +288,7 @@ ComboBox.buttonPressedArrowColor = @buttonPressedArrowColor
|
|||||||
ComboBox.popupInsets = 0,0,0,0
|
ComboBox.popupInsets = 0,0,0,0
|
||||||
ComboBox.selectionInsets = 0,0,0,0
|
ComboBox.selectionInsets = 0,0,0,0
|
||||||
ComboBox.selectionArc = 0
|
ComboBox.selectionArc = 0
|
||||||
|
ComboBox.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
#---- Component ----
|
||||||
@@ -503,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
|
||||||
|
|
||||||
@@ -511,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
|
||||||
|
|
||||||
@@ -668,7 +671,12 @@ SplitPaneDivider.gripGap = 2
|
|||||||
|
|
||||||
TabbedPane.tabHeight = 32
|
TabbedPane.tabHeight = 32
|
||||||
TabbedPane.tabSelectionHeight = 3
|
TabbedPane.tabSelectionHeight = 3
|
||||||
TabbedPane.cardTabSelectionHeight = 2
|
TabbedPane.cardTabSelectionHeight = 3
|
||||||
|
TabbedPane.tabArc = 0
|
||||||
|
TabbedPane.tabSelectionArc = 0
|
||||||
|
TabbedPane.cardTabArc = 12
|
||||||
|
TabbedPane.selectedInsets = 0,0,0,0
|
||||||
|
TabbedPane.tabSelectionInsets = 0,0,0,0
|
||||||
TabbedPane.contentSeparatorHeight = 1
|
TabbedPane.contentSeparatorHeight = 1
|
||||||
TabbedPane.showTabSeparators = false
|
TabbedPane.showTabSeparators = false
|
||||||
TabbedPane.tabSeparatorsFullHeight = false
|
TabbedPane.tabSeparatorsFullHeight = false
|
||||||
@@ -805,6 +813,7 @@ TitlePane.titleMinimumWidth = 60
|
|||||||
TitlePane.buttonSize = 44,30
|
TitlePane.buttonSize = 44,30
|
||||||
TitlePane.buttonMinimumWidth = 30
|
TitlePane.buttonMinimumWidth = 30
|
||||||
TitlePane.buttonMaximizedHeight = 22
|
TitlePane.buttonMaximizedHeight = 22
|
||||||
|
TitlePane.buttonSymbolHeight = 10
|
||||||
TitlePane.centerTitle = false
|
TitlePane.centerTitle = false
|
||||||
TitlePane.centerTitleIfMenuBarEmbedded = true
|
TitlePane.centerTitleIfMenuBarEmbedded = true
|
||||||
TitlePane.showIconBesideTitle = false
|
TitlePane.showIconBesideTitle = false
|
||||||
@@ -826,6 +835,16 @@ TitlePane.closePressedBackground = fade($TitlePane.closeHoverBackground,90%)
|
|||||||
TitlePane.closeHoverForeground = #fff
|
TitlePane.closeHoverForeground = #fff
|
||||||
TitlePane.closePressedForeground = #fff
|
TitlePane.closePressedForeground = #fff
|
||||||
|
|
||||||
|
# window style "small"
|
||||||
|
TitlePane.small.font = -1
|
||||||
|
TitlePane.small.showIcon = false
|
||||||
|
TitlePane.small.buttonSize = 30,20
|
||||||
|
TitlePane.small.buttonSymbolHeight = 8
|
||||||
|
TitlePane.small.closeIcon = com.formdev.flatlaf.icons.FlatWindowCloseIcon, small
|
||||||
|
TitlePane.small.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon, small
|
||||||
|
TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small
|
||||||
|
TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|
||||||
@@ -880,6 +899,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
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
@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)
|
||||||
@@ -338,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
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ infoText = lazy(ToolTip.foreground)
|
|||||||
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
|
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
|
||||||
@accentColor = null
|
@accentColor = null
|
||||||
|
|
||||||
|
# use fixed color because it is used in borders
|
||||||
|
@cellFocusColor = #222
|
||||||
|
|
||||||
|
|
||||||
#---- Button ----
|
#---- Button ----
|
||||||
|
|
||||||
@@ -109,6 +112,9 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
|
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
|
||||||
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
|
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
|
||||||
|
|
||||||
|
@ijTextBackgroundL3 = lighten(Panel.background,3%,lazy)
|
||||||
|
@ijTextBackgroundL4 = lighten(Panel.background,4%,lazy)
|
||||||
|
|
||||||
[Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme]PopupMenu.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||||
@@ -132,53 +138,110 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme_Dark]ProgressBar.selectionBackground = #ddd
|
[Arc_Theme_Dark]ProgressBar.selectionBackground = #ddd
|
||||||
[Arc_Theme_Dark]ProgressBar.selectionForeground = #ddd
|
[Arc_Theme_Dark]ProgressBar.selectionForeground = #ddd
|
||||||
|
[Arc_Theme_Dark]ToolBar.separatorColor = lazy(Separator.foreground)
|
||||||
|
|
||||||
[Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
[Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionBackground = #ddd
|
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionBackground = #ddd
|
||||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionForeground = #fff
|
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionForeground = #fff
|
||||||
|
[Arc_Theme_Dark_-_Orange]ToolBar.separatorColor = lazy(Separator.foreground)
|
||||||
|
|
||||||
|
[Carbon]Table.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Carbon]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||||
|
[Carbon]TextField.background = @ijTextBackgroundL4
|
||||||
|
|
||||||
[Cobalt_2]Component.accentColor = lazy(Component.focusColor)
|
[Cobalt_2]Component.accentColor = lazy(Component.focusColor)
|
||||||
[Cobalt_2]CheckBox.icon.background = #002946
|
[Cobalt_2]CheckBox.icon.background = #002946
|
||||||
[Cobalt_2]CheckBox.icon.checkmarkColor = #002946
|
[Cobalt_2]CheckBox.icon.checkmarkColor = #002946
|
||||||
[Cobalt_2]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Cobalt_2]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Cobalt_2]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Cobalt_2]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
[Cobalt_2]ComboBox.background = @ijTextBackgroundL3
|
||||||
|
[Cobalt_2]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||||
|
[Cobalt_2]TextField.background = @ijTextBackgroundL3
|
||||||
|
[Cobalt_2]Table.background = lazy(List.background)
|
||||||
|
[Cobalt_2]Tree.background = lazy(List.background)
|
||||||
|
|
||||||
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||||
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||||
|
|
||||||
|
[Dark_Flat_Theme]*.inactiveForeground = #808080
|
||||||
[Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
|
[Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
|
||||||
[Dark_Flat_Theme]TableHeader.background = #3B3B3B
|
[Dark_Flat_Theme]TableHeader.background = #3B3B3B
|
||||||
|
[Dark_Flat_Theme]TextPane.foreground = lazy(TextField.foreground)
|
||||||
|
[Dark_Flat_Theme]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
||||||
|
[Dark_Flat_Theme]List.selectionForeground = lazy(Tree.selectionForeground)
|
||||||
|
[Dark_Flat_Theme]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
||||||
|
[Dark_Flat_Theme]Separator.foreground = lazy(ToolBar.separatorColor)
|
||||||
|
|
||||||
[Dark_purple]Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
[Dark_purple]Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
||||||
|
|
||||||
[Dracula---Zihan_Ma]Component.accentColor = lazy(Component.focusColor)
|
[Dracula---Zihan_Ma]Component.accentColor = lazy(Component.focusColor)
|
||||||
|
[Dracula---Zihan_Ma]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||||
[Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
|
[Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
|
||||||
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
||||||
|
|
||||||
|
[Gradianto_Dark_Fuchsia]*.selectionBackground = #8452a7
|
||||||
|
[Gradianto_Dark_Fuchsia]*.selectionInactiveBackground = #562C6A
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
[Gradianto_Dark_Fuchsia]TextField.background = @ijTextBackgroundL4
|
||||||
|
[Gradianto_Dark_Fuchsia]Tree.background = lazy(List.background)
|
||||||
|
[Gradianto_Dark_Fuchsia]Separator.foreground = lazy(ScrollBar.track)
|
||||||
|
[Gradianto_Dark_Fuchsia]ToolBar.separatorColor = lazy(ScrollBar.track)
|
||||||
|
[Gradianto_Dark_Fuchsia]ProgressBar.background = lazy(ScrollBar.track)
|
||||||
|
[Gradianto_Dark_Fuchsia]Slider.trackColor = lazy(ScrollBar.track)
|
||||||
|
|
||||||
|
[Gradianto_Deep_Ocean]TextField.background = @ijTextBackgroundL3
|
||||||
|
[Gradianto_Deep_Ocean]Tree.background = lazy(List.background)
|
||||||
|
|
||||||
|
[Gradianto_Midnight_Blue]ScrollBar.thumb = #533B6B
|
||||||
|
[Gradianto_Midnight_Blue]Table.selectionForeground = lazy(List.selectionForeground)
|
||||||
|
[Gradianto_Midnight_Blue]TextField.background = @ijTextBackgroundL4
|
||||||
|
[Gradianto_Midnight_Blue]Tree.background = lazy(List.background)
|
||||||
|
|
||||||
|
[Gradianto_Nature_Green]Table.selectionForeground = lazy(List.selectionForeground)
|
||||||
|
[Gradianto_Nature_Green]TextField.background = @ijTextBackgroundL4
|
||||||
|
|
||||||
|
[Gray]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Gray]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
[Gruvbox_Dark_Hard]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Gruvbox_Dark_Hard]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Gruvbox_Dark_Hard]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
[Gruvbox_Dark_Hard]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||||
[Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
[Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||||
|
[Gruvbox_Dark_Hard]ComboBox.background = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Hard]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Hard]TextField.background = @ijTextBackgroundL3
|
||||||
|
|
||||||
[Gruvbox_Dark_Medium]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Gruvbox_Dark_Medium]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||||
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||||
|
[Gruvbox_Dark_Medium]ComboBox.background = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Medium]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Medium]TextField.background = @ijTextBackgroundL3
|
||||||
|
|
||||||
[Gruvbox_Dark_Soft]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Gruvbox_Dark_Soft]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Gruvbox_Dark_Soft]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Gruvbox_Dark_Soft]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gruvbox_Dark_Soft]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Gruvbox_Dark_Soft]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||||
|
[Gruvbox_Dark_Soft]ComboBox.background = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Soft]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||||
|
[Gruvbox_Dark_Soft]TextField.background = @ijTextBackgroundL3
|
||||||
|
|
||||||
|
[Hiberbee_Dark]*.disabledForeground = #7F7E7D
|
||||||
|
[Hiberbee_Dark]*.disabledText = #7F7E7D
|
||||||
|
[Hiberbee_Dark]*.inactiveForeground = #7F7E7D
|
||||||
|
[Hiberbee_Dark]ProgressBar.background = lazy(Separator.foreground)
|
||||||
|
[Hiberbee_Dark]Slider.trackColor = lazy(Separator.foreground)
|
||||||
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
||||||
[Hiberbee_Dark]TabbedPane.selectedBackground = #434241
|
[Hiberbee_Dark]TabbedPane.selectedBackground = #434241
|
||||||
[Hiberbee_Dark]TabbedPane.selectedForeground = #70D7FF
|
[Hiberbee_Dark]TabbedPane.selectedForeground = #70D7FF
|
||||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||||
|
[Hiberbee_Dark]Table.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
||||||
|
[Hiberbee_Dark]Tree.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Hiberbee_Dark]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
||||||
|
|
||||||
[High_contrast]Component.accentColor = lazy(Component.focusColor)
|
[High_contrast]Component.accentColor = lazy(Component.focusColor)
|
||||||
[High_contrast]ToggleButton.selectedBackground = #fff
|
[High_contrast]ToggleButton.selectedBackground = #fff
|
||||||
@@ -191,9 +254,20 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
toolbar.selectedBackground: #fff
|
toolbar.selectedBackground: #fff
|
||||||
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
|
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
|
||||||
|
|
||||||
|
[Light_Flat]*.disabledForeground = #8C8C8C
|
||||||
|
[Light_Flat]*.inactiveForeground = #8C8C8C
|
||||||
|
[Light_Flat]CheckBox.icon[filled].background = #fff
|
||||||
|
[Light_Flat]CheckBox.icon[filled].checkmarkColor = #fff
|
||||||
[Light_Flat]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Light_Flat]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
|
[Light_Flat]ComboBox.background = lazy(ComboBox.editableBackground)
|
||||||
|
[Light_Flat]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
|
||||||
|
[Light_Flat]Separator.foreground = lazy(ToolBar.separatorColor)
|
||||||
[Light_Flat]TableHeader.background = #E5E5E9
|
[Light_Flat]TableHeader.background = #E5E5E9
|
||||||
|
[Light_Flat]TextPane.foreground = lazy(TextField.foreground)
|
||||||
|
[Light_Flat]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
||||||
|
[Light_Flat]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
|
||||||
|
|
||||||
|
[Monocai]Button.default.foreground = #2D2A2F
|
||||||
[Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Monocai]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Monocai]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
@Monocai.acceleratorForeground = lazy(MenuItem.disabledForeground)
|
@Monocai.acceleratorForeground = lazy(MenuItem.disabledForeground)
|
||||||
@@ -206,22 +280,67 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[Monocai]MenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
[Monocai]MenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
||||||
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
||||||
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
||||||
|
[Monocai]TextField.background = @ijTextBackgroundL4
|
||||||
|
@Monocai.selectionBackground = lazy(TextField.selectionBackground)
|
||||||
|
[Monocai]ComboBox.selectionBackground = @Monocai.selectionBackground
|
||||||
|
[Monocai]List.selectionBackground = @Monocai.selectionBackground
|
||||||
|
[Monocai]Table.selectionBackground = @Monocai.selectionBackground
|
||||||
|
[Monocai]Tree.selectionBackground = @Monocai.selectionBackground
|
||||||
|
@Monocai.selectionInactiveBackground = lazy(MenuItem.selectionBackground)
|
||||||
|
[Monocai]List.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
|
[Monocai]Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
|
[Monocai]Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||||
|
|
||||||
[Monokai_Pro]TitledBorder.titleColor = @foreground
|
[Monokai_Pro---Subtheme]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||||
|
[Monokai_Pro---Subtheme]Tree.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Monokai_Pro---Subtheme]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Monokai_Pro---Subtheme]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
|
[Nord]*.inactiveForeground = #616E88
|
||||||
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
[Nord]List.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[Nord]List.selectionForeground = lazy(Tree.selectionForeground)
|
||||||
|
[Nord]Table.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[Nord]Table.selectionForeground = lazy(Tree.selectionForeground)
|
||||||
|
[Nord]TextField.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[Nord]TextField.selectionForeground = lazy(Tree.selectionForeground)
|
||||||
|
[Nord]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||||
|
|
||||||
|
[NotReallyMDTheme]*.selectionInactiveBackground = #21384E
|
||||||
|
[NotReallyMDTheme]ToolBar.separatorColor = lazy(Separator.foreground)
|
||||||
|
|
||||||
|
[One_Dark]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
||||||
[One_Dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[One_Dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
[One_Dark]ProgressBar.background = lazy(Separator.foreground)
|
||||||
|
[One_Dark]Slider.trackColor = lazy(Separator.foreground)
|
||||||
[One_Dark]Slider.focusedColor = fade(#568af2,40%)
|
[One_Dark]Slider.focusedColor = fade(#568af2,40%)
|
||||||
|
[One_Dark]Table.background = lazy(Tree.background)
|
||||||
|
[One_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[One_Dark]TextField.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[One_Dark]Tree.selectionForeground = lazy(List.selectionForeground)
|
||||||
|
|
||||||
|
[Solarized_Dark---4lex4]*.inactiveForeground = #657B83
|
||||||
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
|
[Solarized_Dark---4lex4]ComboBox.background = lazy(ComboBox.editableBackground)
|
||||||
|
[Solarized_Dark---4lex4]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
|
||||||
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
||||||
|
[Solarized_Dark---4lex4]ToolBar.separatorColor = lazy(Separator.foreground)
|
||||||
|
|
||||||
|
[Solarized_Light---4lex4]*.inactiveForeground = #839496
|
||||||
[Solarized_Light---4lex4]Button.default.hoverBackground = darken($Button.default.background,3%,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)
|
||||||
|
|
||||||
|
[Spacegray]ComboBox.background = @ijTextBackgroundL4
|
||||||
|
[Spacegray]ComboBox.buttonBackground = @ijTextBackgroundL4
|
||||||
|
[Spacegray]TextField.background = @ijTextBackgroundL4
|
||||||
|
[Spacegray]TextField.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[Spacegray]TextField.selectionForeground = lazy(Tree.selectionForeground)
|
||||||
|
|
||||||
|
[vuesion-theme]*.disabledForeground = #8C8C8C
|
||||||
|
[vuesion-theme]*.disabledText = #8C8C8C
|
||||||
|
[vuesion-theme]*.inactiveForeground = #8C8C8C
|
||||||
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
||||||
[vuesion-theme]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[vuesion-theme]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[vuesion-theme]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[vuesion-theme]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
@@ -229,6 +348,12 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[vuesion-theme]Slider.trackColor = #303a45
|
[vuesion-theme]Slider.trackColor = #303a45
|
||||||
[vuesion-theme]Slider.thumbColor = #ececee
|
[vuesion-theme]Slider.thumbColor = #ececee
|
||||||
[vuesion-theme]Slider.focusedColor = fade(#ececee,20%)
|
[vuesion-theme]Slider.focusedColor = fade(#ececee,20%)
|
||||||
|
[vuesion-theme]ComboBox.background = @ijTextBackgroundL4
|
||||||
|
[vuesion-theme]ComboBox.buttonBackground = @ijTextBackgroundL4
|
||||||
|
[vuesion-theme]TextField.background = @ijTextBackgroundL4
|
||||||
|
[vuesion-theme]TextField.selectionBackground = lighten(#303A45,15%)
|
||||||
|
|
||||||
|
[Xcode-Dark]TextField.background = @ijTextBackgroundL4
|
||||||
|
|
||||||
|
|
||||||
# Material Theme UI Lite
|
# Material Theme UI Lite
|
||||||
@@ -238,62 +363,106 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[dark][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
[dark][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||||
[dark][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
[dark][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||||
|
|
||||||
|
[author-Mallowigi]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
|
||||||
|
|
||||||
|
[Arc_Dark]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Arc_Dark]Table.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
|
||||||
|
[Atom_One_Dark]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Atom_One_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
|
[Atom_One_Light]List.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[Atom_One_Light]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[Atom_One_Light]TabbedPane.contentAreaColor = lazy(Separator.foreground)
|
||||||
|
|
||||||
|
[Dracula---Mallowigi]*.selectionBackground = #44475A
|
||||||
|
[Dracula---Mallowigi]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
||||||
[Dracula---Mallowigi]ProgressBar.selectionBackground = #fff
|
[Dracula---Mallowigi]ProgressBar.selectionBackground = #fff
|
||||||
[Dracula---Mallowigi]ProgressBar.selectionForeground = #fff
|
[Dracula---Mallowigi]ProgressBar.selectionForeground = #fff
|
||||||
|
[Dracula---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(CheckBoxMenuItem.selectionForeground)
|
||||||
[Dracula_Contrast]ProgressBar.selectionBackground = #fff
|
[Dracula---Mallowigi]Table.selectionForeground = lazy(List.selectionForeground)
|
||||||
[Dracula_Contrast]ProgressBar.selectionForeground = #fff
|
[Dracula---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Dracula---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
[GitHub]ProgressBar.selectionBackground = #222
|
[GitHub]ProgressBar.selectionBackground = #222
|
||||||
[GitHub]ProgressBar.selectionForeground = #222
|
[GitHub]ProgressBar.selectionForeground = #222
|
||||||
|
[GitHub]TextField.background = @ijTextBackgroundL3
|
||||||
|
[GitHub]List.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[GitHub]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
|
||||||
[GitHub_Contrast]ProgressBar.selectionBackground = #222
|
[GitHub_Dark]ComboBox.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
[GitHub_Contrast]ProgressBar.selectionForeground = #222
|
[GitHub_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
|
||||||
|
[GitHub_Dark]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[GitHub_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
|
[Light_Owl]CheckBoxMenuItem.selectionForeground = lazy(CheckBoxMenuItem.foreground)
|
||||||
|
[Light_Owl]ComboBox.selectionForeground = lazy(ComboBox.foreground)
|
||||||
[Light_Owl]List.selectionInactiveForeground = lazy(List.foreground)
|
[Light_Owl]List.selectionInactiveForeground = lazy(List.foreground)
|
||||||
|
[Light_Owl]Menu.selectionForeground = lazy(Menu.foreground)
|
||||||
|
[Light_Owl]MenuBar.selectionForeground = lazy(MenuBar.foreground)
|
||||||
|
[Light_Owl]MenuItem.selectionForeground = lazy(MenuItem.foreground)
|
||||||
[Light_Owl]ProgressBar.selectionBackground = #111
|
[Light_Owl]ProgressBar.selectionBackground = #111
|
||||||
[Light_Owl]ProgressBar.selectionForeground = #fff
|
[Light_Owl]ProgressBar.selectionForeground = #fff
|
||||||
[Light_Owl]TabbedPane.selectedForeground = lazy(TabbedPane.foreground)
|
[Light_Owl]Spinner.selectionForeground = lazy(Spinner.foreground)
|
||||||
[Light_Owl]Table.selectionForeground = lazy(Table.foreground)
|
[Light_Owl]Table.selectionForeground = lazy(Table.foreground)
|
||||||
|
[Light_Owl]TextField.selectionForeground = lazy(TextField.foreground)
|
||||||
|
[Light_Owl]TextField.background = @ijTextBackgroundL3
|
||||||
|
[Light_Owl]List.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[Light_Owl]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
|
||||||
[Light_Owl_Contrast]List.selectionInactiveForeground = lazy(List.foreground)
|
[Material_Darker]*.selectionBackground = lighten(#2D2D2D,15%)
|
||||||
[Light_Owl_Contrast]ProgressBar.selectionBackground = #111
|
[Material_Darker]Separator.foreground = lazy(Slider.trackColor)
|
||||||
[Light_Owl_Contrast]ProgressBar.selectionForeground = #fff
|
[Material_Darker]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
[Light_Owl_Contrast]TabbedPane.selectedForeground = lazy(TabbedPane.foreground)
|
|
||||||
[Light_Owl_Contrast]Table.selectionForeground = lazy(Table.foreground)
|
|
||||||
|
|
||||||
|
[Material_Deep_Ocean]*.selectionBackground = lighten(#222533,15%)
|
||||||
|
[Material_Deep_Ocean]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Material_Deep_Ocean]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
|
[Material_Lighter]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
|
||||||
[Material_Lighter]ProgressBar.selectionBackground = #222
|
[Material_Lighter]ProgressBar.selectionBackground = #222
|
||||||
[Material_Lighter]ProgressBar.selectionForeground = #fff
|
[Material_Lighter]ProgressBar.selectionForeground = #fff
|
||||||
|
[Material_Lighter]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||||
[Material_Lighter_Contrast]ProgressBar.selectionBackground = #222
|
[Material_Lighter]Table.selectionBackground = lazy(List.selectionBackground)
|
||||||
[Material_Lighter_Contrast]ProgressBar.selectionForeground = #fff
|
[Material_Lighter]List.selectionForeground = lazy(Table.selectionForeground)
|
||||||
|
[Material_Lighter]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
|
||||||
|
[Material_Lighter]Tree.selectionForeground = lazy(Table.selectionForeground)
|
||||||
|
|
||||||
[Material_Oceanic]ProgressBar.selectionBackground = #ddd
|
[Material_Oceanic]ProgressBar.selectionBackground = #ddd
|
||||||
[Material_Oceanic]ProgressBar.selectionForeground = #ddd
|
[Material_Oceanic]ProgressBar.selectionForeground = #ddd
|
||||||
|
[Material_Oceanic]Separator.foreground = lazy(Slider.trackColor)
|
||||||
[Material_Oceanic_Contrast]ProgressBar.selectionBackground = #ddd
|
[Material_Oceanic]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
[Material_Oceanic_Contrast]ProgressBar.selectionForeground = #ddd
|
|
||||||
|
|
||||||
[Material_Palenight]ProgressBar.selectionBackground = #ddd
|
[Material_Palenight]ProgressBar.selectionBackground = #ddd
|
||||||
[Material_Palenight]ProgressBar.selectionForeground = #ddd
|
[Material_Palenight]ProgressBar.selectionForeground = #ddd
|
||||||
|
[Material_Palenight]List.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[Material_Palenight]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||||
|
[Material_Palenight]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Material_Palenight]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
[Material_Palenight_Contrast]ProgressBar.selectionBackground = #ddd
|
[Monokai_Pro---Mallowigi]List.selectionForeground = lazy(Table.selectionForeground)
|
||||||
[Material_Palenight_Contrast]ProgressBar.selectionForeground = #ddd
|
[Monokai_Pro---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
|
||||||
|
[Monokai_Pro---Mallowigi]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||||
|
[Monokai_Pro---Mallowigi]Tree.selectionForeground = lazy(Table.selectionForeground)
|
||||||
|
[Monokai_Pro---Mallowigi]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||||
|
[Monokai_Pro---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Monokai_Pro---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
|
[Moonlight]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Moonlight]Table.selectionBackground = lazy(List.selectionBackground)
|
||||||
|
[Moonlight]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Moonlight]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|
||||||
[Night_Owl]ProgressBar.selectionBackground = #ddd
|
[Night_Owl]ProgressBar.selectionBackground = #ddd
|
||||||
[Night_Owl]ProgressBar.selectionForeground = #ddd
|
[Night_Owl]ProgressBar.selectionForeground = #ddd
|
||||||
|
|
||||||
[Night_Owl_Contrast]ProgressBar.selectionBackground = #ddd
|
|
||||||
[Night_Owl_Contrast]ProgressBar.selectionForeground = #ddd
|
|
||||||
|
|
||||||
[Solarized_Dark---Mallowigi]ProgressBar.selectionBackground = #ccc
|
[Solarized_Dark---Mallowigi]ProgressBar.selectionBackground = #ccc
|
||||||
[Solarized_Dark---Mallowigi]ProgressBar.selectionForeground = #ccc
|
[Solarized_Dark---Mallowigi]ProgressBar.selectionForeground = #ccc
|
||||||
|
[Solarized_Dark---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
||||||
[Solarized_Dark_Contrast]ProgressBar.selectionBackground = #ccc
|
[Solarized_Dark---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
[Solarized_Dark_Contrast]ProgressBar.selectionForeground = #ccc
|
|
||||||
|
|
||||||
[Solarized_Light---Mallowigi]ProgressBar.selectionBackground = #222
|
[Solarized_Light---Mallowigi]ProgressBar.selectionBackground = #222
|
||||||
[Solarized_Light---Mallowigi]ProgressBar.selectionForeground = #fff
|
[Solarized_Light---Mallowigi]ProgressBar.selectionForeground = #fff
|
||||||
|
[Solarized_Light---Mallowigi]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||||
[Solarized_Light_Contrast]ProgressBar.selectionBackground = #222
|
[Solarized_Light---Mallowigi]Table.selectionBackground = lazy(List.selectionBackground)
|
||||||
[Solarized_Light_Contrast]ProgressBar.selectionForeground = #fff
|
[Solarized_Light---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
|
||||||
|
[Solarized_Light---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,42 +12,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
#---- FileChooser ----
|
|
||||||
|
|
||||||
#fields
|
|
||||||
FileChooser.lookInLabel.textAndMnemonic = Look &In:
|
|
||||||
FileChooser.saveInLabelText = Save In:
|
|
||||||
FileChooser.fileNameLabel.textAndMnemonic = File &Name:
|
|
||||||
FileChooser.folderNameLabel.textAndMnemonic = Folder &name:
|
|
||||||
FileChooser.filesOfTypeLabel.textAndMnemonic = Files of &Type:
|
|
||||||
|
|
||||||
# toolbar
|
|
||||||
FileChooser.upFolderToolTipText = Up One Level
|
|
||||||
FileChooser.upFolderAccessibleName = Up
|
|
||||||
FileChooser.homeFolderToolTipText = Home
|
|
||||||
FileChooser.homeFolderAccessibleName = Home
|
|
||||||
FileChooser.newFolderToolTipText = Create New Folder
|
|
||||||
FileChooser.newFolderAccessibleName = New Folder
|
|
||||||
FileChooser.listViewButtonToolTipText = List
|
|
||||||
FileChooser.listViewButtonAccessibleName = List
|
|
||||||
FileChooser.detailsViewButtonToolTipText = Details
|
|
||||||
FileChooser.detailsViewButtonAccessibleName = Details
|
|
||||||
|
|
||||||
# details table header
|
|
||||||
FileChooser.fileNameHeaderText = Name
|
|
||||||
FileChooser.fileSizeHeaderText = Size
|
|
||||||
FileChooser.fileTypeHeaderText = Type
|
|
||||||
FileChooser.fileDateHeaderText = Modified
|
|
||||||
FileChooser.fileAttrHeaderText = Attributes
|
|
||||||
|
|
||||||
# popup menu
|
|
||||||
FileChooser.viewMenuLabelText = View
|
|
||||||
FileChooser.refreshActionLabelText = Refresh
|
|
||||||
FileChooser.newFolderActionLabelText = New Folder
|
|
||||||
FileChooser.listViewActionLabelText = List
|
|
||||||
FileChooser.detailsViewActionLabelText = Details
|
|
||||||
|
|
||||||
|
|
||||||
#---- SplitPaneDivider ----
|
#---- SplitPaneDivider ----
|
||||||
|
|
||||||
SplitPaneDivider.collapseLeftToolTipText = Collapse Left Pane
|
SplitPaneDivider.collapseLeftToolTipText = Collapse Left Pane
|
||||||
|
|||||||
@@ -12,42 +12,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
#---- FileChooser ----
|
|
||||||
|
|
||||||
#fields
|
|
||||||
FileChooser.lookInLabel.textAndMnemonic = Suchen &in:
|
|
||||||
FileChooser.saveInLabelText = Speichern in:
|
|
||||||
FileChooser.fileNameLabel.textAndMnemonic = &Dateiname:
|
|
||||||
FileChooser.folderNameLabel.textAndMnemonic = Ordner&name:
|
|
||||||
FileChooser.filesOfTypeLabel.textAndMnemonic = Datei&typ:
|
|
||||||
|
|
||||||
# toolbar
|
|
||||||
FileChooser.upFolderToolTipText = Eine Ebene h\u00F6her
|
|
||||||
FileChooser.upFolderAccessibleName = Nach oben
|
|
||||||
FileChooser.homeFolderToolTipText = Home
|
|
||||||
FileChooser.homeFolderAccessibleName = Home
|
|
||||||
FileChooser.newFolderToolTipText = Neuen Ordner erstellen
|
|
||||||
FileChooser.newFolderAccessibleName = Neuer Ordner
|
|
||||||
FileChooser.listViewButtonToolTipText = Liste
|
|
||||||
FileChooser.listViewButtonAccessibleName = Liste
|
|
||||||
FileChooser.detailsViewButtonToolTipText = Details
|
|
||||||
FileChooser.detailsViewButtonAccessibleName = Details
|
|
||||||
|
|
||||||
# details table header
|
|
||||||
FileChooser.fileNameHeaderText = Name
|
|
||||||
FileChooser.fileSizeHeaderText = Gr\u00F6\u00DFe
|
|
||||||
FileChooser.fileTypeHeaderText = Typ
|
|
||||||
FileChooser.fileDateHeaderText = \u00C4nderungsdatum
|
|
||||||
FileChooser.fileAttrHeaderText = Attribute
|
|
||||||
|
|
||||||
# popup menu
|
|
||||||
FileChooser.viewMenuLabelText = Ansicht
|
|
||||||
FileChooser.refreshActionLabelText = Aktualisieren
|
|
||||||
FileChooser.newFolderActionLabelText = Neuer Ordner
|
|
||||||
FileChooser.listViewActionLabelText = Liste
|
|
||||||
FileChooser.detailsViewActionLabelText = Details
|
|
||||||
|
|
||||||
|
|
||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.moreTabsButtonToolTipText = Verdeckte Tabs anzeigen
|
TabbedPane.moreTabsButtonToolTipText = Verdeckte Tabs anzeigen
|
||||||
|
|||||||
@@ -12,42 +12,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
#---- FileChooser ----
|
|
||||||
|
|
||||||
#fields
|
|
||||||
FileChooser.lookInLabel.textAndMnemonic = Buscar &en:
|
|
||||||
FileChooser.saveInLabelText = Guardar en:
|
|
||||||
FileChooser.fileNameLabel.textAndMnemonic = &Nombre de fichero:
|
|
||||||
FileChooser.folderNameLabel.textAndMnemonic = &Nombre de carpeta:
|
|
||||||
FileChooser.filesOfTypeLabel.textAndMnemonic = Ficheros de &Tipo:
|
|
||||||
|
|
||||||
# toolbar
|
|
||||||
FileChooser.upFolderToolTipText = Subir un nivel
|
|
||||||
FileChooser.upFolderAccessibleName = Subir
|
|
||||||
FileChooser.homeFolderToolTipText = Inicio
|
|
||||||
FileChooser.homeFolderAccessibleName = Inicio
|
|
||||||
FileChooser.newFolderToolTipText = Crear nueva carpeta
|
|
||||||
FileChooser.newFolderAccessibleName = Nueva carpeta
|
|
||||||
FileChooser.listViewButtonToolTipText = Lista
|
|
||||||
FileChooser.listViewButtonAccessibleName = Lista
|
|
||||||
FileChooser.detailsViewButtonToolTipText = Detalles
|
|
||||||
FileChooser.detailsViewButtonAccessibleName = Detalles
|
|
||||||
|
|
||||||
# details table header
|
|
||||||
FileChooser.fileNameHeaderText = Nombre
|
|
||||||
FileChooser.fileSizeHeaderText = Tama\u00F1o
|
|
||||||
FileChooser.fileTypeHeaderText = Tipo
|
|
||||||
FileChooser.fileDateHeaderText = Modificado
|
|
||||||
FileChooser.fileAttrHeaderText = Atributos
|
|
||||||
|
|
||||||
# popup menu
|
|
||||||
FileChooser.viewMenuLabelText = Ver
|
|
||||||
FileChooser.refreshActionLabelText = Refrescar
|
|
||||||
FileChooser.newFolderActionLabelText = Nueva carpeta
|
|
||||||
FileChooser.listViewActionLabelText = Lista
|
|
||||||
FileChooser.detailsViewActionLabelText = Detalles
|
|
||||||
|
|
||||||
|
|
||||||
#---- SplitPaneDivider ----
|
#---- SplitPaneDivider ----
|
||||||
|
|
||||||
SplitPaneDivider.collapseLeftToolTipText = Contraer Panel Izquierdo
|
SplitPaneDivider.collapseLeftToolTipText = Contraer Panel Izquierdo
|
||||||
|
|||||||
@@ -12,37 +12,3 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
#---- FileChooser ----
|
|
||||||
|
|
||||||
#fields
|
|
||||||
FileChooser.lookInLabel.textAndMnemonic = Rechercher &dans:
|
|
||||||
FileChooser.saveInLabelText = Enregistrer dans:
|
|
||||||
FileChooser.fileNameLabel.textAndMnemonic = &Nom du fichier:
|
|
||||||
FileChooser.folderNameLabel.textAndMnemonic = &Nom du dossier:
|
|
||||||
FileChooser.filesOfTypeLabel.textAndMnemonic = &Type de fichier:
|
|
||||||
|
|
||||||
# toolbar
|
|
||||||
FileChooser.upFolderToolTipText = Remonte d'un niveau
|
|
||||||
FileChooser.upFolderAccessibleName = Monter
|
|
||||||
FileChooser.homeFolderToolTipText = R\u00E9pertoire de base
|
|
||||||
FileChooser.homeFolderAccessibleName = R\u00E9pertoire de base
|
|
||||||
FileChooser.newFolderToolTipText = Cr\u00E9e un dossier
|
|
||||||
FileChooser.newFolderAccessibleName = Nouveau dossier
|
|
||||||
FileChooser.listViewButtonToolTipText = Liste
|
|
||||||
FileChooser.listViewButtonAccessibleName = Liste
|
|
||||||
FileChooser.detailsViewButtonToolTipText = D\u00E9tails
|
|
||||||
FileChooser.detailsViewButtonAccessibleName = D\u00E9tails
|
|
||||||
|
|
||||||
# details table header
|
|
||||||
FileChooser.fileNameHeaderText = Nom
|
|
||||||
FileChooser.fileSizeHeaderText = Taille
|
|
||||||
FileChooser.fileTypeHeaderText = Type
|
|
||||||
FileChooser.fileDateHeaderText = Modifi\u00E9
|
|
||||||
FileChooser.fileAttrHeaderText = Attributs
|
|
||||||
|
|
||||||
# popup menu
|
|
||||||
FileChooser.viewMenuLabelText = Affichage
|
|
||||||
FileChooser.refreshActionLabelText = Actualiser
|
|
||||||
FileChooser.newFolderActionLabelText = Nouveau dossier
|
|
||||||
FileChooser.listViewActionLabelText = Liste
|
|
||||||
FileChooser.detailsViewActionLabelText = D\u00E9tails
|
|
||||||
|
|||||||
@@ -67,11 +67,11 @@
|
|||||||
@nsControlAccentColor = #007aff
|
@nsControlAccentColor = #007aff
|
||||||
|
|
||||||
# accent colors are:
|
# accent colors are:
|
||||||
# @nsSelectedTextBackgroundColor
|
# @nsSelectedTextBackgroundColor for @textSelectionBackground
|
||||||
# @nsSelectedContentBackgroundColor
|
# @nsSelectedContentBackgroundColor for @selectionBackground
|
||||||
# @nsSelectedControlColor
|
# @nsSelectedControlColor unused
|
||||||
# @nsKeyboardFocusIndicatorColor
|
# @nsKeyboardFocusIndicatorColor for @accentFocusColor
|
||||||
# @nsControlAccentColor
|
# @nsControlAccentColor for @accentColor
|
||||||
|
|
||||||
|
|
||||||
#---- variables ----
|
#---- variables ----
|
||||||
@@ -88,12 +88,12 @@
|
|||||||
@menuBackground = lighten(@background,8%)
|
@menuBackground = lighten(@background,8%)
|
||||||
|
|
||||||
# selection
|
# selection
|
||||||
@selectionBackground = if(systemColor(accent), shade(spin(systemColor(accent),4),20%), @nsSelectedContentBackgroundColor)
|
@selectionBackground = shade(spin(if(systemColor(accent), systemColor(accent), @accentColor),4),20%)
|
||||||
@selectionForeground = @nsSelectedMenuItemTextColor
|
@selectionForeground = @nsSelectedMenuItemTextColor
|
||||||
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
||||||
|
|
||||||
# text selection
|
# text selection
|
||||||
@textSelectionBackground = systemColor(highlight,if(systemColor(accent), darken(desaturate(systemColor(accent),60%),10%), @nsSelectedTextBackgroundColor))
|
@textSelectionBackground = systemColor(highlight,darken(desaturate(if(systemColor(accent), systemColor(accent), @accentColor),60%),10%))
|
||||||
@textSelectionForeground = @nsSelectedTextColor
|
@textSelectionForeground = @nsSelectedTextColor
|
||||||
|
|
||||||
# menu
|
# menu
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
@accentColor = systemColor(accent,@nsControlAccentColor)
|
@accentColor = systemColor(accent,@nsControlAccentColor)
|
||||||
@accentFocusColor = if(systemColor(accent), fade(spin(systemColor(accent),-10),50%), @nsKeyboardFocusIndicatorColor)
|
@accentFocusColor = fade(lighten(spin(if(systemColor(accent), systemColor(accent), @accentColor),-8),5%),50%)
|
||||||
|
|
||||||
|
|
||||||
#---- Button ----
|
#---- Button ----
|
||||||
@@ -149,6 +149,7 @@ ComboBox.selectionBackground = @menuSelectionBackground
|
|||||||
ComboBox.popupInsets = 5,0,5,0
|
ComboBox.popupInsets = 5,0,5,0
|
||||||
ComboBox.selectionInsets = 0,5,0,5
|
ComboBox.selectionInsets = 0,5,0,5
|
||||||
ComboBox.selectionArc = 8
|
ComboBox.selectionArc = 8
|
||||||
|
ComboBox.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
#---- Component ----
|
||||||
@@ -205,6 +206,7 @@ PasswordField.selectionForeground = @textSelectionForeground
|
|||||||
#---- PopupMenu ----
|
#---- PopupMenu ----
|
||||||
|
|
||||||
PopupMenu.borderInsets = 6,1,6,1
|
PopupMenu.borderInsets = 6,1,6,1
|
||||||
|
PopupMenu.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
#---- ProgressBar ----
|
#---- ProgressBar ----
|
||||||
@@ -259,6 +261,13 @@ Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,20%,derived
|
|||||||
Spinner.buttonSeparatorWidth = 0
|
Spinner.buttonSeparatorWidth = 0
|
||||||
|
|
||||||
|
|
||||||
|
#---- TabbedPane ----
|
||||||
|
|
||||||
|
TabbedPane.tabArc = $Button.arc
|
||||||
|
TabbedPane.tabSelectionArc = 999
|
||||||
|
TabbedPane.cardTabArc = $Button.arc
|
||||||
|
|
||||||
|
|
||||||
#---- TextArea ---
|
#---- TextArea ---
|
||||||
|
|
||||||
TextArea.disabledBackground = @disabledComponentBackground
|
TextArea.disabledBackground = @disabledComponentBackground
|
||||||
|
|||||||
@@ -67,11 +67,11 @@
|
|||||||
@nsControlAccentColor = #007aff
|
@nsControlAccentColor = #007aff
|
||||||
|
|
||||||
# accent colors are:
|
# accent colors are:
|
||||||
# @nsSelectedTextBackgroundColor
|
# @nsSelectedTextBackgroundColor for @textSelectionBackground
|
||||||
# @nsSelectedContentBackgroundColor
|
# @nsSelectedContentBackgroundColor for @selectionBackground
|
||||||
# @nsSelectedControlColor
|
# @nsSelectedControlColor unused
|
||||||
# @nsKeyboardFocusIndicatorColor
|
# @nsKeyboardFocusIndicatorColor for @accentFocusColor
|
||||||
# @nsControlAccentColor
|
# @nsControlAccentColor for @accentColor
|
||||||
|
|
||||||
|
|
||||||
#---- variables ----
|
#---- variables ----
|
||||||
@@ -88,12 +88,12 @@
|
|||||||
@menuBackground = darken(@background,4%)
|
@menuBackground = darken(@background,4%)
|
||||||
|
|
||||||
# selection
|
# selection
|
||||||
@selectionBackground = if(systemColor(accent), shade(spin(systemColor(accent),4),10%), @nsSelectedContentBackgroundColor)
|
@selectionBackground = shade(spin(if(systemColor(accent), systemColor(accent), @accentColor),4),10%)
|
||||||
@selectionForeground = @nsSelectedMenuItemTextColor
|
@selectionForeground = @nsSelectedMenuItemTextColor
|
||||||
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
|
||||||
|
|
||||||
# text selection
|
# text selection
|
||||||
@textSelectionBackground = systemColor(highlight,if(systemColor(accent), tint(systemColor(accent),70%), @nsSelectedTextBackgroundColor))
|
@textSelectionBackground = systemColor(highlight,tint(if(systemColor(accent), systemColor(accent), @accentColor),70%))
|
||||||
@textSelectionForeground = @foreground
|
@textSelectionForeground = @foreground
|
||||||
|
|
||||||
# menu
|
# menu
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
|
|
||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
@accentColor = systemColor(accent,@nsControlAccentColor)
|
@accentColor = systemColor(accent,@nsControlAccentColor)
|
||||||
@accentFocusColor = if(systemColor(accent), fade(spin(systemColor(accent),4),50%), @nsKeyboardFocusIndicatorColor)
|
@accentFocusColor = fade(spin(if(systemColor(accent), systemColor(accent), @accentColor),4),50%)
|
||||||
|
|
||||||
|
|
||||||
#---- Button ----
|
#---- Button ----
|
||||||
@@ -150,6 +150,7 @@ ComboBox.selectionBackground = @menuSelectionBackground
|
|||||||
ComboBox.popupInsets = 5,0,5,0
|
ComboBox.popupInsets = 5,0,5,0
|
||||||
ComboBox.selectionInsets = 0,5,0,5
|
ComboBox.selectionInsets = 0,5,0,5
|
||||||
ComboBox.selectionArc = 8
|
ComboBox.selectionArc = 8
|
||||||
|
ComboBox.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
#---- Component ----
|
||||||
@@ -206,6 +207,7 @@ PasswordField.selectionForeground = @textSelectionForeground
|
|||||||
#---- PopupMenu ----
|
#---- PopupMenu ----
|
||||||
|
|
||||||
PopupMenu.borderInsets = 6,1,6,1
|
PopupMenu.borderInsets = 6,1,6,1
|
||||||
|
PopupMenu.borderCornerRadius = 8
|
||||||
|
|
||||||
|
|
||||||
#---- ProgressBar ----
|
#---- ProgressBar ----
|
||||||
@@ -258,6 +260,13 @@ Spinner.buttonHoverArrowColor = lighten($Spinner.buttonArrowColor,20%,derived no
|
|||||||
Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,30%,derived noAutoInverse)
|
Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,30%,derived noAutoInverse)
|
||||||
|
|
||||||
|
|
||||||
|
#---- TabbedPane ----
|
||||||
|
|
||||||
|
TabbedPane.tabArc = $Button.arc
|
||||||
|
TabbedPane.tabSelectionArc = 999
|
||||||
|
TabbedPane.cardTabArc = $Button.arc
|
||||||
|
|
||||||
|
|
||||||
#---- TextArea ---
|
#---- TextArea ---
|
||||||
|
|
||||||
TextArea.disabledBackground = @disabledComponentBackground
|
TextArea.disabledBackground = @disabledComponentBackground
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.UIDefaults.ActiveValue;
|
import javax.swing.UIDefaults.ActiveValue;
|
||||||
@@ -153,4 +154,103 @@ public class TestUIDefaultsLoader
|
|||||||
new Font( name, style, size ),
|
new Font( name, style, size ),
|
||||||
((ActiveValue)UIDefaultsLoader.parseValue( "dummyFont", actualStyle, null )).createValue( null ) );
|
((ActiveValue)UIDefaultsLoader.parseValue( "dummyFont", actualStyle, null )).createValue( null ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseInstance() {
|
||||||
|
String className = TestInstance.class.getName();
|
||||||
|
assertEquals( new TestInstance(), ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", className, null )).createValue( null ) );
|
||||||
|
assertInstanceEquals( new TestInstance(), null );
|
||||||
|
assertInstanceEquals( new TestInstance( "some string" ), "some string" );
|
||||||
|
assertInstanceEquals( new TestInstance( false ), "false" );
|
||||||
|
assertInstanceEquals( new TestInstance( true ), "true" );
|
||||||
|
assertInstanceEquals( new TestInstance( 123 ), "123" );
|
||||||
|
assertInstanceEquals( new TestInstance( 123.456f ), "123.456" );
|
||||||
|
assertInstanceEquals( new TestInstance( Color.red ), "#f00" );
|
||||||
|
assertInstanceEquals( new TestInstance( "some string", true ), "some string, true" );
|
||||||
|
assertInstanceEquals( new TestInstance( "some string", true, 123 ), "some string, true, 123" );
|
||||||
|
assertInstanceEquals( new TestInstance( "some string", 123, true ), "some string, 123, true" );
|
||||||
|
assertInstanceEquals( new TestInstance( "some string", 123.456f, true ), "some string, 123.456, true" );
|
||||||
|
assertInstanceEquals( new TestInstance( 123, "some string" ), "123, some string" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertInstanceEquals( TestInstance expected, String params ) {
|
||||||
|
String value = TestInstance.class.getName() + (params != null ? "," + params : "");
|
||||||
|
assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class TestInstance -------------------------------------------------
|
||||||
|
|
||||||
|
@SuppressWarnings( "EqualsHashCode" ) // Error Prone
|
||||||
|
public static class TestInstance
|
||||||
|
{
|
||||||
|
private String s;
|
||||||
|
private boolean b;
|
||||||
|
private int i;
|
||||||
|
private float f;
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
public TestInstance() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( String s ) {
|
||||||
|
this.s = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( boolean b ) {
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( int i ) {
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( float f ) {
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( Color color ) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( String s, boolean b ) {
|
||||||
|
this.s = s;
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( String s, boolean b, int i ) {
|
||||||
|
this.s = s;
|
||||||
|
this.b = b;
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( String s, int i, boolean b ) {
|
||||||
|
this.s = s;
|
||||||
|
this.b = b;
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestInstance( String s, float f, boolean b ) {
|
||||||
|
this.s = s;
|
||||||
|
this.b = b;
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestInstance( int i, String s ) {
|
||||||
|
this.s = s;
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object obj ) {
|
||||||
|
if( !(obj instanceof TestInstance) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TestInstance inst = (TestInstance) obj;
|
||||||
|
return Objects.equals( s, inst.s ) &&
|
||||||
|
b == inst.b &&
|
||||||
|
i == inst.i &&
|
||||||
|
f == inst.f &&
|
||||||
|
Objects.equals( color, inst.color );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -721,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,
|
||||||
|
|
||||||
@@ -730,6 +732,11 @@ public class TestFlatStyleableInfo
|
|||||||
"tabHeight", int.class,
|
"tabHeight", int.class,
|
||||||
"tabSelectionHeight", int.class,
|
"tabSelectionHeight", int.class,
|
||||||
"cardTabSelectionHeight", int.class,
|
"cardTabSelectionHeight", int.class,
|
||||||
|
"tabArc", int.class,
|
||||||
|
"tabSelectionArc", int.class,
|
||||||
|
"cardTabArc", int.class,
|
||||||
|
"selectedInsets", Insets.class,
|
||||||
|
"tabSelectionInsets", Insets.class,
|
||||||
"contentSeparatorHeight", int.class,
|
"contentSeparatorHeight", int.class,
|
||||||
"showTabSeparators", boolean.class,
|
"showTabSeparators", boolean.class,
|
||||||
"tabSeparatorsFullHeight", boolean.class,
|
"tabSeparatorsFullHeight", boolean.class,
|
||||||
@@ -804,6 +811,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,
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|
||||||
@@ -736,6 +738,11 @@ public class TestFlatStyleableValue
|
|||||||
testInteger( c, ui, "tabHeight", 123 );
|
testInteger( c, ui, "tabHeight", 123 );
|
||||||
testInteger( c, ui, "tabSelectionHeight", 123 );
|
testInteger( c, ui, "tabSelectionHeight", 123 );
|
||||||
testInteger( c, ui, "cardTabSelectionHeight", 123 );
|
testInteger( c, ui, "cardTabSelectionHeight", 123 );
|
||||||
|
testInteger( c, ui, "tabArc", 123 );
|
||||||
|
testInteger( c, ui, "tabSelectionArc", 123 );
|
||||||
|
testInteger( c, ui, "cardTabArc", 123 );
|
||||||
|
testInsets( c, ui, "selectedInsets", 1,2,3,4 );
|
||||||
|
testInsets( c, ui, "tabSelectionInsets", 1,2,3,4 );
|
||||||
testInteger( c, ui, "contentSeparatorHeight", 123 );
|
testInteger( c, ui, "contentSeparatorHeight", 123 );
|
||||||
testBoolean( c, ui, "showTabSeparators", false );
|
testBoolean( c, ui, "showTabSeparators", false );
|
||||||
testBoolean( c, ui, "tabSeparatorsFullHeight", false );
|
testBoolean( c, ui, "tabSeparatorsFullHeight", false );
|
||||||
@@ -802,6 +809,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" );
|
||||||
@@ -1208,6 +1219,7 @@ public class TestFlatStyleableValue
|
|||||||
|
|
||||||
//---- class TestIcon -----------------------------------------------------
|
//---- class TestIcon -----------------------------------------------------
|
||||||
|
|
||||||
|
@SuppressWarnings( "EqualsHashCode" ) // Error Prone
|
||||||
public static class TestIcon
|
public static class TestIcon
|
||||||
implements Icon
|
implements Icon
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
@@ -890,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" );
|
||||||
|
|
||||||
@@ -899,6 +917,11 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "tabHeight: 30" );
|
ui.applyStyle( "tabHeight: 30" );
|
||||||
ui.applyStyle( "tabSelectionHeight: 3" );
|
ui.applyStyle( "tabSelectionHeight: 3" );
|
||||||
ui.applyStyle( "cardTabSelectionHeight: 2" );
|
ui.applyStyle( "cardTabSelectionHeight: 2" );
|
||||||
|
ui.applyStyle( "tabArc: 3" );
|
||||||
|
ui.applyStyle( "tabSelectionArc: 4" );
|
||||||
|
ui.applyStyle( "cardTabArc: 5" );
|
||||||
|
ui.applyStyle( "selectedInsets: 1,2,3,4" );
|
||||||
|
ui.applyStyle( "tabSelectionInsets: 1,2,3,4" );
|
||||||
ui.applyStyle( "contentSeparatorHeight: 1" );
|
ui.applyStyle( "contentSeparatorHeight: 1" );
|
||||||
ui.applyStyle( "showTabSeparators: false" );
|
ui.applyStyle( "showTabSeparators: false" );
|
||||||
ui.applyStyle( "tabSeparatorsFullHeight: false" );
|
ui.applyStyle( "tabSeparatorsFullHeight: false" );
|
||||||
@@ -983,6 +1006,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" );
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import javax.swing.*;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class TestFlatStylingScale
|
||||||
|
{
|
||||||
|
private static final float[] FACTORS = { 1f, 1.5f, 2f };
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() {
|
||||||
|
TestUtils.setup( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void cleanup() {
|
||||||
|
TestUtils.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static float[] factors() {
|
||||||
|
return FACTORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void button( float factor ) {
|
||||||
|
abstractButton( factor, new JButton() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void checkBox( float factor ) {
|
||||||
|
abstractButton( factor, new JCheckBox() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void radioButton( float factor ) {
|
||||||
|
abstractButton( factor, new JRadioButton() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void abstractButton( float factor, AbstractButton button ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
button.putClientProperty( FlatClientProperties.STYLE, "iconTextGap: 100" );
|
||||||
|
assertEquals( (int) (100 * factor), button.getIconTextGap() );
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void tabbedPane( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
|
||||||
|
JTabbedPane tabbedPane = new JTabbedPane();
|
||||||
|
FlatTabbedPaneUI ui = (FlatTabbedPaneUI) tabbedPane.getUI();
|
||||||
|
tabbedPane.putClientProperty( FlatClientProperties.STYLE, "textIconGap: 100" );
|
||||||
|
assertEquals( 100, ui.getStyleableValue( tabbedPane, "textIconGap" ) );
|
||||||
|
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void table( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
|
||||||
|
JTable table = new JTable();
|
||||||
|
table.putClientProperty( FlatClientProperties.STYLE, "rowHeight: 100" );
|
||||||
|
assertEquals( (int) (100 * factor), table.getRowHeight() );
|
||||||
|
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource( "factors" )
|
||||||
|
void tree( float factor ) {
|
||||||
|
TestUtils.scaleFont( factor );
|
||||||
|
|
||||||
|
|
||||||
|
JTree tree = new JTree();
|
||||||
|
tree.putClientProperty( FlatClientProperties.STYLE, "rowHeight: 10" );
|
||||||
|
assertEquals( 10 * factor, tree.getRowHeight() );
|
||||||
|
|
||||||
|
|
||||||
|
TestUtils.resetFont();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
|||||||
*/
|
*/
|
||||||
public class TestUtils
|
public class TestUtils
|
||||||
{
|
{
|
||||||
|
@SuppressWarnings( "MutablePublicArray" ) // Error Prone
|
||||||
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 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 ) {
|
||||||
|
|||||||
2
flatlaf-demo/.settings/org.eclipse.core.resources.prefs
Normal file
2
flatlaf-demo/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=ISO-8859-1
|
||||||
@@ -27,8 +27,8 @@ dependencies {
|
|||||||
implementation( project( ":flatlaf-fonts-roboto" ) )
|
implementation( project( ":flatlaf-fonts-roboto" ) )
|
||||||
implementation( project( ":flatlaf-fonts-roboto-mono" ) )
|
implementation( project( ":flatlaf-fonts-roboto-mono" ) )
|
||||||
implementation( project( ":flatlaf-intellij-themes" ) )
|
implementation( project( ":flatlaf-intellij-themes" ) )
|
||||||
implementation( "com.miglayout:miglayout-swing:5.3" )
|
implementation( libs.miglayout.swing )
|
||||||
implementation( "com.jgoodies:jgoodies-forms:1.9.0" )
|
implementation( libs.jgoodies.forms )
|
||||||
// implementation( project( ":flatlaf-natives-jna" ) )
|
// implementation( project( ":flatlaf-natives-jna" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -440,9 +440,9 @@ class DemoFrame
|
|||||||
|
|
||||||
Class<? extends LookAndFeel> lafClass = UIManager.getLookAndFeel().getClass();
|
Class<? extends LookAndFeel> lafClass = UIManager.getLookAndFeel().getClass();
|
||||||
try {
|
try {
|
||||||
FlatLaf.setup( lafClass.newInstance() );
|
FlatLaf.setup( lafClass.getDeclaredConstructor().newInstance() );
|
||||||
FlatLaf.updateUI();
|
FlatLaf.updateUI();
|
||||||
} catch( InstantiationException | IllegalAccessException ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,6 +591,7 @@ class DemoFrame
|
|||||||
undoMenuItem.setText("Undo");
|
undoMenuItem.setText("Undo");
|
||||||
undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
undoMenuItem.setMnemonic('U');
|
undoMenuItem.setMnemonic('U');
|
||||||
|
undoMenuItem.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/undo.svg"));
|
||||||
undoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
undoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||||
editMenu.add(undoMenuItem);
|
editMenu.add(undoMenuItem);
|
||||||
|
|
||||||
@@ -598,6 +599,7 @@ class DemoFrame
|
|||||||
redoMenuItem.setText("Redo");
|
redoMenuItem.setText("Redo");
|
||||||
redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
redoMenuItem.setMnemonic('R');
|
redoMenuItem.setMnemonic('R');
|
||||||
|
redoMenuItem.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/redo.svg"));
|
||||||
redoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
redoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||||
editMenu.add(redoMenuItem);
|
editMenu.add(redoMenuItem);
|
||||||
editMenu.addSeparator();
|
editMenu.addSeparator();
|
||||||
@@ -606,18 +608,21 @@ class DemoFrame
|
|||||||
cutMenuItem.setText("Cut");
|
cutMenuItem.setText("Cut");
|
||||||
cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
cutMenuItem.setMnemonic('C');
|
cutMenuItem.setMnemonic('C');
|
||||||
|
cutMenuItem.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-cut.svg"));
|
||||||
editMenu.add(cutMenuItem);
|
editMenu.add(cutMenuItem);
|
||||||
|
|
||||||
//---- copyMenuItem ----
|
//---- copyMenuItem ----
|
||||||
copyMenuItem.setText("Copy");
|
copyMenuItem.setText("Copy");
|
||||||
copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
copyMenuItem.setMnemonic('O');
|
copyMenuItem.setMnemonic('O');
|
||||||
|
copyMenuItem.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/copy.svg"));
|
||||||
editMenu.add(copyMenuItem);
|
editMenu.add(copyMenuItem);
|
||||||
|
|
||||||
//---- pasteMenuItem ----
|
//---- pasteMenuItem ----
|
||||||
pasteMenuItem.setText("Paste");
|
pasteMenuItem.setText("Paste");
|
||||||
pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
pasteMenuItem.setMnemonic('P');
|
pasteMenuItem.setMnemonic('P');
|
||||||
|
pasteMenuItem.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-paste.svg"));
|
||||||
editMenu.add(pasteMenuItem);
|
editMenu.add(pasteMenuItem);
|
||||||
editMenu.addSeparator();
|
editMenu.addSeparator();
|
||||||
|
|
||||||
@@ -827,34 +832,41 @@ class DemoFrame
|
|||||||
|
|
||||||
//---- backButton ----
|
//---- backButton ----
|
||||||
backButton.setToolTipText("Back");
|
backButton.setToolTipText("Back");
|
||||||
|
backButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/back.svg"));
|
||||||
toolBar.add(backButton);
|
toolBar.add(backButton);
|
||||||
|
|
||||||
//---- forwardButton ----
|
//---- forwardButton ----
|
||||||
forwardButton.setToolTipText("Forward");
|
forwardButton.setToolTipText("Forward");
|
||||||
|
forwardButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/forward.svg"));
|
||||||
toolBar.add(forwardButton);
|
toolBar.add(forwardButton);
|
||||||
toolBar.addSeparator();
|
toolBar.addSeparator();
|
||||||
|
|
||||||
//---- cutButton ----
|
//---- cutButton ----
|
||||||
cutButton.setToolTipText("Cut");
|
cutButton.setToolTipText("Cut");
|
||||||
|
cutButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-cut.svg"));
|
||||||
toolBar.add(cutButton);
|
toolBar.add(cutButton);
|
||||||
|
|
||||||
//---- copyButton ----
|
//---- copyButton ----
|
||||||
copyButton.setToolTipText("Copy");
|
copyButton.setToolTipText("Copy");
|
||||||
|
copyButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/copy.svg"));
|
||||||
toolBar.add(copyButton);
|
toolBar.add(copyButton);
|
||||||
|
|
||||||
//---- pasteButton ----
|
//---- pasteButton ----
|
||||||
pasteButton.setToolTipText("Paste");
|
pasteButton.setToolTipText("Paste");
|
||||||
|
pasteButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/menu-paste.svg"));
|
||||||
toolBar.add(pasteButton);
|
toolBar.add(pasteButton);
|
||||||
toolBar.addSeparator();
|
toolBar.addSeparator();
|
||||||
|
|
||||||
//---- refreshButton ----
|
//---- refreshButton ----
|
||||||
refreshButton.setToolTipText("Refresh");
|
refreshButton.setToolTipText("Refresh");
|
||||||
|
refreshButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/refresh.svg"));
|
||||||
toolBar.add(refreshButton);
|
toolBar.add(refreshButton);
|
||||||
toolBar.addSeparator();
|
toolBar.addSeparator();
|
||||||
|
|
||||||
//---- showToggleButton ----
|
//---- showToggleButton ----
|
||||||
showToggleButton.setSelected(true);
|
showToggleButton.setSelected(true);
|
||||||
showToggleButton.setToolTipText("Show Details");
|
showToggleButton.setToolTipText("Show Details");
|
||||||
|
showToggleButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/show.svg"));
|
||||||
toolBar.add(showToggleButton);
|
toolBar.add(showToggleButton);
|
||||||
}
|
}
|
||||||
contentPane.add(toolBar, BorderLayout.NORTH);
|
contentPane.add(toolBar, BorderLayout.NORTH);
|
||||||
@@ -901,21 +913,6 @@ class DemoFrame
|
|||||||
menuBar1.add( Box.createGlue() );
|
menuBar1.add( Box.createGlue() );
|
||||||
menuBar1.add( usersButton );
|
menuBar1.add( usersButton );
|
||||||
|
|
||||||
undoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/undo.svg" ) );
|
|
||||||
redoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/redo.svg" ) );
|
|
||||||
|
|
||||||
cutMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/menu-cut.svg" ) );
|
|
||||||
copyMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/copy.svg" ) );
|
|
||||||
pasteMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/menu-paste.svg" ) );
|
|
||||||
|
|
||||||
backButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/back.svg" ) );
|
|
||||||
forwardButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/forward.svg" ) );
|
|
||||||
cutButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/menu-cut.svg" ) );
|
|
||||||
copyButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/copy.svg" ) );
|
|
||||||
pasteButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/menu-paste.svg" ) );
|
|
||||||
refreshButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/refresh.svg" ) );
|
|
||||||
showToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/show.svg" ) );
|
|
||||||
|
|
||||||
cutMenuItem.addActionListener( new DefaultEditorKit.CutAction() );
|
cutMenuItem.addActionListener( new DefaultEditorKit.CutAction() );
|
||||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||||
@@ -950,6 +947,9 @@ class DemoFrame
|
|||||||
if( SystemInfo.isMacOS )
|
if( SystemInfo.isMacOS )
|
||||||
unsupported( underlineMenuSelectionMenuItem );
|
unsupported( underlineMenuSelectionMenuItem );
|
||||||
|
|
||||||
|
if( "false".equals( System.getProperty( "flatlaf.animatedLafChange" ) ) )
|
||||||
|
animatedLafChangeMenuItem.setSelected( false );
|
||||||
|
|
||||||
// remove contentPanel bottom insets
|
// remove contentPanel bottom insets
|
||||||
MigLayout layout = (MigLayout) contentPanel.getLayout();
|
MigLayout layout = (MigLayout) contentPanel.getLayout();
|
||||||
LC lc = ConstraintParser.parseLayoutConstraint( (String) layout.getLayoutConstraints() );
|
LC lc = ConstraintParser.parseLayoutConstraint( (String) layout.getLayoutConstraints() );
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
JFDML JFormDesigner: "7.0.4.0.360" Java: "17" encoding: "UTF-8"
|
JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
|
||||||
|
|
||||||
new FormModel {
|
new FormModel {
|
||||||
contentType: "form/swing"
|
contentType: "form/swing"
|
||||||
@@ -21,10 +21,12 @@ new FormModel {
|
|||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "backButton"
|
name: "backButton"
|
||||||
"toolTipText": "Back"
|
"toolTipText": "Back"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/back.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "forwardButton"
|
name: "forwardButton"
|
||||||
"toolTipText": "Forward"
|
"toolTipText": "Forward"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/forward.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||||
name: "separator5"
|
name: "separator5"
|
||||||
@@ -32,14 +34,17 @@ new FormModel {
|
|||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "cutButton"
|
name: "cutButton"
|
||||||
"toolTipText": "Cut"
|
"toolTipText": "Cut"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-cut.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "copyButton"
|
name: "copyButton"
|
||||||
"toolTipText": "Copy"
|
"toolTipText": "Copy"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/copy.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "pasteButton"
|
name: "pasteButton"
|
||||||
"toolTipText": "Paste"
|
"toolTipText": "Paste"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-paste.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||||
name: "separator6"
|
name: "separator6"
|
||||||
@@ -47,6 +52,7 @@ new FormModel {
|
|||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "refreshButton"
|
name: "refreshButton"
|
||||||
"toolTipText": "Refresh"
|
"toolTipText": "Refresh"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/refresh.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||||
name: "separator7"
|
name: "separator7"
|
||||||
@@ -55,6 +61,7 @@ new FormModel {
|
|||||||
name: "showToggleButton"
|
name: "showToggleButton"
|
||||||
"selected": true
|
"selected": true
|
||||||
"toolTipText": "Show Details"
|
"toolTipText": "Show Details"
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/show.svg" )
|
||||||
} )
|
} )
|
||||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||||
"value": "North"
|
"value": "North"
|
||||||
@@ -185,6 +192,7 @@ new FormModel {
|
|||||||
"text": "Undo"
|
"text": "Undo"
|
||||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 90, 4226, false )
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 90, 4226, false )
|
||||||
"mnemonic": 85
|
"mnemonic": 85
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/undo.svg" )
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
@@ -192,6 +200,7 @@ new FormModel {
|
|||||||
"text": "Redo"
|
"text": "Redo"
|
||||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 89, 4226, false )
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 89, 4226, false )
|
||||||
"mnemonic": 82
|
"mnemonic": 82
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/redo.svg" )
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||||
@@ -202,18 +211,21 @@ new FormModel {
|
|||||||
"text": "Cut"
|
"text": "Cut"
|
||||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 88, 4226, false )
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 88, 4226, false )
|
||||||
"mnemonic": 67
|
"mnemonic": 67
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-cut.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
name: "copyMenuItem"
|
name: "copyMenuItem"
|
||||||
"text": "Copy"
|
"text": "Copy"
|
||||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 67, 4226, false )
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 67, 4226, false )
|
||||||
"mnemonic": 79
|
"mnemonic": 79
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/copy.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
name: "pasteMenuItem"
|
name: "pasteMenuItem"
|
||||||
"text": "Paste"
|
"text": "Paste"
|
||||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 86, 4226, false )
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 86, 4226, false )
|
||||||
"mnemonic": 80
|
"mnemonic": 80
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/menu-paste.svg" )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||||
name: "separator3"
|
name: "separator3"
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ public class FlatLafDemo
|
|||||||
// - "system": use current macOS appearance (light or dark)
|
// - "system": use current macOS appearance (light or dark)
|
||||||
// - "NSAppearanceNameAqua": use light appearance
|
// - "NSAppearanceNameAqua": use light appearance
|
||||||
// - "NSAppearanceNameDarkAqua": use dark appearance
|
// - "NSAppearanceNameDarkAqua": use dark appearance
|
||||||
// (needs to be set on main thread; setting it on AWT thread does not work)
|
// (must be set on main thread and before AWT/Swing is initialized;
|
||||||
|
// setting it on AWT thread does not work)
|
||||||
System.setProperty( "apple.awt.application.appearance", "system" );
|
System.setProperty( "apple.awt.application.appearance", "system" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -82,14 +83,13 @@ public class IJThemesPanel
|
|||||||
|
|
||||||
private File lastDirectory;
|
private File lastDirectory;
|
||||||
private boolean isAdjustingThemesList;
|
private boolean isAdjustingThemesList;
|
||||||
|
private long lastLafChangeTime = System.currentTimeMillis();
|
||||||
|
|
||||||
public IJThemesPanel() {
|
public IJThemesPanel() {
|
||||||
initComponents();
|
initComponents();
|
||||||
|
|
||||||
saveButton.setEnabled( false );
|
saveButton.setEnabled( false );
|
||||||
sourceCodeButton.setEnabled( false );
|
sourceCodeButton.setEnabled( false );
|
||||||
saveButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/download.svg" ) );
|
|
||||||
sourceCodeButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/github.svg" ) );
|
|
||||||
|
|
||||||
// create renderer
|
// create renderer
|
||||||
themesList.setCellRenderer( new DefaultListCellRenderer() {
|
themesList.setCellRenderer( new DefaultListCellRenderer() {
|
||||||
@@ -370,7 +370,10 @@ public class IJThemesPanel
|
|||||||
if( themeInfo == null || themeInfo.resourceName == null )
|
if( themeInfo == null || themeInfo.resourceName == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String themeUrl = (themeInfo.sourceCodeUrl + '/' + themeInfo.sourceCodePath).replace( " ", "%20" );
|
String themeUrl = themeInfo.sourceCodeUrl;
|
||||||
|
if( themeInfo.sourceCodePath != null )
|
||||||
|
themeUrl += '/' + themeInfo.sourceCodePath;
|
||||||
|
themeUrl = themeUrl.replace( " ", "%20" );
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse( new URI( themeUrl ) );
|
Desktop.getDesktop().browse( new URI( themeUrl ) );
|
||||||
} catch( IOException | URISyntaxException ex ) {
|
} catch( IOException | URISyntaxException ex ) {
|
||||||
@@ -409,14 +412,59 @@ public class IJThemesPanel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void lafChanged( PropertyChangeEvent e ) {
|
private void lafChanged( PropertyChangeEvent e ) {
|
||||||
if( "lookAndFeel".equals( e.getPropertyName() ) )
|
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
|
||||||
selectedCurrentLookAndFeel();
|
selectedCurrentLookAndFeel();
|
||||||
|
lastLafChangeTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void windowActivated() {
|
private void windowActivated() {
|
||||||
// refresh themes list on window activation
|
// refresh themes list on window activation
|
||||||
if( themesManager.hasThemesFromDirectoryChanged() )
|
if( themesManager.hasThemesFromDirectoryChanged() )
|
||||||
updateThemesList();
|
updateThemesList();
|
||||||
|
else {
|
||||||
|
// check whether core .properties files of current Laf have changed
|
||||||
|
// in development environment since last Laf change and reload theme
|
||||||
|
LookAndFeel laf = UIManager.getLookAndFeel();
|
||||||
|
if( laf instanceof FlatLaf ) {
|
||||||
|
List<Class<?>> lafClasses = new ArrayList<>();
|
||||||
|
|
||||||
|
if( laf instanceof IntelliJTheme.ThemeLaf ) {
|
||||||
|
boolean dark = ((FlatLaf)laf).isDark();
|
||||||
|
lafClasses.add( FlatLaf.class );
|
||||||
|
lafClasses.add( dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
||||||
|
lafClasses.add( dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
||||||
|
lafClasses.add( IntelliJTheme.ThemeLaf.class );
|
||||||
|
} else {
|
||||||
|
for( Class<?> lafClass = laf.getClass();
|
||||||
|
FlatLaf.class.isAssignableFrom( lafClass );
|
||||||
|
lafClass = lafClass.getSuperclass() )
|
||||||
|
{
|
||||||
|
lafClasses.add( 0, lafClass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean reload = false;
|
||||||
|
for( Class<?> lafClass : lafClasses ) {
|
||||||
|
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
|
||||||
|
URL url = lafClass.getResource( propertiesName );
|
||||||
|
if( url != null && "file".equals( url.getProtocol() ) ) {
|
||||||
|
try {
|
||||||
|
File file = new File( url.toURI() );
|
||||||
|
if( file.lastModified() > lastLafChangeTime ) {
|
||||||
|
reload = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch( URISyntaxException ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( reload )
|
||||||
|
setTheme( themesList.getSelectedValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectedCurrentLookAndFeel() {
|
private void selectedCurrentLookAndFeel() {
|
||||||
@@ -488,11 +536,13 @@ public class IJThemesPanel
|
|||||||
|
|
||||||
//---- saveButton ----
|
//---- saveButton ----
|
||||||
saveButton.setToolTipText("Save .theme.json of selected IntelliJ theme to file.");
|
saveButton.setToolTipText("Save .theme.json of selected IntelliJ theme to file.");
|
||||||
|
saveButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/download.svg"));
|
||||||
saveButton.addActionListener(e -> saveTheme());
|
saveButton.addActionListener(e -> saveTheme());
|
||||||
toolBar.add(saveButton);
|
toolBar.add(saveButton);
|
||||||
|
|
||||||
//---- sourceCodeButton ----
|
//---- sourceCodeButton ----
|
||||||
sourceCodeButton.setToolTipText("Opens the source code repository of selected IntelliJ theme in the browser.");
|
sourceCodeButton.setToolTipText("Opens the source code repository of selected IntelliJ theme in the browser.");
|
||||||
|
sourceCodeButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/github.svg"));
|
||||||
sourceCodeButton.addActionListener(e -> browseSourceCode());
|
sourceCodeButton.addActionListener(e -> browseSourceCode());
|
||||||
toolBar.add(sourceCodeButton);
|
toolBar.add(sourceCodeButton);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "14" encoding: "UTF-8"
|
JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
|
||||||
|
|
||||||
new FormModel {
|
new FormModel {
|
||||||
contentType: "form/swing"
|
contentType: "form/swing"
|
||||||
@@ -24,11 +24,13 @@ new FormModel {
|
|||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "saveButton"
|
name: "saveButton"
|
||||||
"toolTipText": "Save .theme.json of selected IntelliJ theme to file."
|
"toolTipText": "Save .theme.json of selected IntelliJ theme to file."
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/download.svg" )
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveTheme", false ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveTheme", false ) )
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JButton" ) {
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
name: "sourceCodeButton"
|
name: "sourceCodeButton"
|
||||||
"toolTipText": "Opens the source code repository of selected IntelliJ theme in the browser."
|
"toolTipText": "Opens the source code repository of selected IntelliJ theme in the browser."
|
||||||
|
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/github.svg" )
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "browseSourceCode", false ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "browseSourceCode", false ) )
|
||||||
} )
|
} )
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
|||||||
@@ -38,8 +38,10 @@ public class IJThemesUpdater
|
|||||||
themesManager.loadBundledThemes();
|
themesManager.loadBundledThemes();
|
||||||
|
|
||||||
for( IJThemeInfo ti : themesManager.bundledThemes ) {
|
for( IJThemeInfo ti : themesManager.bundledThemes ) {
|
||||||
if( ti.sourceCodeUrl == null || ti.sourceCodePath == null )
|
if( ti.sourceCodeUrl == null || ti.sourceCodePath == null ) {
|
||||||
|
System.out.println( " " + ti.name + " NOT downloaded. Needs manual update from release on JetBrains Plugin portal." );
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String fromUrl = ti.sourceCodeUrl + "/" + ti.sourceCodePath;
|
String fromUrl = ti.sourceCodeUrl + "/" + ti.sourceCodePath;
|
||||||
if( fromUrl.contains( "github.com" ) )
|
if( fromUrl.contains( "github.com" ) )
|
||||||
|
|||||||
@@ -144,8 +144,8 @@
|
|||||||
"dark": true,
|
"dark": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "Hiberbee.LICENSE.txt",
|
"licenseFile": "Hiberbee.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/Hiberbee/code-highlight-themes",
|
"sourceCodeUrl": "https://github.com/Hiberbee/themes",
|
||||||
"sourceCodePath": "blob/latest/src/main/resources/HiberbeeDark.theme.json"
|
"sourceCodePath": "blob/latest/src/intellij/src/main/resources/themes/HiberbeeDark.theme.json"
|
||||||
},
|
},
|
||||||
"HighContrast.theme.json": {
|
"HighContrast.theme.json": {
|
||||||
"name": "High contrast",
|
"name": "High contrast",
|
||||||
@@ -247,15 +247,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Arc Dark.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Arc Dark.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Arc Dark Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Arc Dark Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Arc Dark Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Atom One Dark.theme.json": {
|
"material-theme-ui-lite/Atom One Dark.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Atom One Dark",
|
"name": "Material Theme UI Lite / Atom One Dark",
|
||||||
@@ -263,29 +255,14 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Atom One Dark.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Dark.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Atom One Dark Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Atom One Dark Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Atom One Dark Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Atom One Light.theme.json": {
|
"material-theme-ui-lite/Atom One Light.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Atom One Light",
|
"name": "Material Theme UI Lite / Atom One Light",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Atom One Light.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Light.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Atom One Light Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Atom One Light Contrast",
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Atom One Light Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Dracula.theme.json": {
|
"material-theme-ui-lite/Dracula.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Dracula",
|
"name": "Material Theme UI Lite / Dracula",
|
||||||
@@ -293,29 +270,14 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Dracula.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Dracula.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Dracula Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Dracula Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Dracula Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/GitHub.theme.json": {
|
"material-theme-ui-lite/GitHub.theme.json": {
|
||||||
"name": "Material Theme UI Lite / GitHub",
|
"name": "Material Theme UI Lite / GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/GitHub.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/GitHub Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / GitHub Contrast",
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/GitHub Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/GitHub Dark.theme.json": {
|
"material-theme-ui-lite/GitHub Dark.theme.json": {
|
||||||
"name": "Material Theme UI Lite / GitHub Dark",
|
"name": "Material Theme UI Lite / GitHub Dark",
|
||||||
@@ -323,29 +285,14 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/GitHub Dark.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub Dark.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/GitHub Dark Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / GitHub Dark Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/GitHub Dark Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Light Owl.theme.json": {
|
"material-theme-ui-lite/Light Owl.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Light Owl",
|
"name": "Material Theme UI Lite / Light Owl",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Light Owl.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Light Owl.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Light Owl Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Light Owl Contrast",
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Light Owl Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Material Darker.theme.json": {
|
"material-theme-ui-lite/Material Darker.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Material Darker",
|
"name": "Material Theme UI Lite / Material Darker",
|
||||||
@@ -353,15 +300,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Darker.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Darker.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Material Darker Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Material Darker Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Darker Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Material Deep Ocean.theme.json": {
|
"material-theme-ui-lite/Material Deep Ocean.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Material Deep Ocean",
|
"name": "Material Theme UI Lite / Material Deep Ocean",
|
||||||
@@ -369,29 +308,14 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Deep Ocean.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Deep Ocean.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Material Deep Ocean Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Material Deep Ocean Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Deep Ocean Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Material Lighter.theme.json": {
|
"material-theme-ui-lite/Material Lighter.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Material Lighter",
|
"name": "Material Theme UI Lite / Material Lighter",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Lighter.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Lighter.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Material Lighter Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Material Lighter Contrast",
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Lighter Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Material Oceanic.theme.json": {
|
"material-theme-ui-lite/Material Oceanic.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Material Oceanic",
|
"name": "Material Theme UI Lite / Material Oceanic",
|
||||||
@@ -399,15 +323,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Oceanic.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Oceanic.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Material Oceanic Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Material Oceanic Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Oceanic Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Material Palenight.theme.json": {
|
"material-theme-ui-lite/Material Palenight.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Material Palenight",
|
"name": "Material Theme UI Lite / Material Palenight",
|
||||||
@@ -415,15 +331,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Palenight.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Palenight.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Material Palenight Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Material Palenight Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Material Palenight Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Monokai Pro.theme.json": {
|
"material-theme-ui-lite/Monokai Pro.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Monokai Pro",
|
"name": "Material Theme UI Lite / Monokai Pro",
|
||||||
@@ -431,15 +339,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Monokai Pro.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Monokai Pro.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Monokai Pro Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Monokai Pro Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Monokai Pro Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Moonlight.theme.json": {
|
"material-theme-ui-lite/Moonlight.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Moonlight",
|
"name": "Material Theme UI Lite / Moonlight",
|
||||||
@@ -447,15 +347,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Moonlight.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Moonlight.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Moonlight Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Moonlight Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Moonlight Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Night Owl.theme.json": {
|
"material-theme-ui-lite/Night Owl.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Night Owl",
|
"name": "Material Theme UI Lite / Night Owl",
|
||||||
@@ -463,15 +355,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Night Owl.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Night Owl.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Night Owl Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Night Owl Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Night Owl Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Solarized Dark.theme.json": {
|
"material-theme-ui-lite/Solarized Dark.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Solarized Dark",
|
"name": "Material Theme UI Lite / Solarized Dark",
|
||||||
@@ -479,28 +363,13 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Solarized Dark.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Dark.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Solarized Dark Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Solarized Dark Contrast",
|
|
||||||
"dark": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Solarized Dark Contrast.theme.json"
|
|
||||||
},
|
},
|
||||||
"material-theme-ui-lite/Solarized Light.theme.json": {
|
"material-theme-ui-lite/Solarized Light.theme.json": {
|
||||||
"name": "Material Theme UI Lite / Solarized Light",
|
"name": "Material Theme UI Lite / Solarized Light",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Solarized Light.theme.json"
|
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Light.theme.json"
|
||||||
},
|
|
||||||
"material-theme-ui-lite/Solarized Light Contrast.theme.json": {
|
|
||||||
"name": "Material Theme UI Lite / Solarized Light Contrast",
|
|
||||||
"license": "MIT",
|
|
||||||
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
|
|
||||||
"sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
|
|
||||||
"sourceCodePath": "blob/master/src/main/resources/themes/Solarized Light Contrast.theme.json"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=ISO-8859-1
|
||||||
@@ -4,8 +4,7 @@ FlatLaf Extras
|
|||||||
This sub-project provides some additional components and classes:
|
This sub-project provides some additional components and classes:
|
||||||
|
|
||||||
- [FlatSVGIcon](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/FlatSVGIcon.html):
|
- [FlatSVGIcon](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/FlatSVGIcon.html):
|
||||||
An icon that displays SVG using
|
An icon that displays SVG using [JSVG](https://github.com/weisJ/jsvg).\
|
||||||
[svgSalamander](https://github.com/JFormDesigner/svgSalamander).\
|
|
||||||

|

|
||||||
- [FlatTriStateCheckBox](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html):
|
- [FlatTriStateCheckBox](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html):
|
||||||
A tri-state check box.\
|
A tri-state check box.\
|
||||||
@@ -38,9 +37,9 @@ Otherwise download `flatlaf-extras-<version>.jar` here:
|
|||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-extras)
|
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-extras)
|
||||||
|
|
||||||
If SVG classes are used, `svgSalamander-<version>.jar` is also required:
|
If SVG classes are used, `jsvg-<version>.jar` is also required:
|
||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/svgSalamander)
|
[](https://maven-badges.herokuapp.com/maven-central/com.github.weisj/jsvg)
|
||||||
|
|
||||||
|
|
||||||
Tools
|
Tools
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ plugins {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation( project( ":flatlaf-core" ) )
|
implementation( project( ":flatlaf-core" ) )
|
||||||
implementation( "com.formdev:svgSalamander:1.1.3" )
|
implementation( libs.jsvg )
|
||||||
}
|
}
|
||||||
|
|
||||||
flatlafModuleInfo {
|
flatlafModuleInfo {
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import java.awt.image.RGBImageFilter;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -49,9 +49,9 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||||
import com.formdev.flatlaf.util.SoftCache;
|
import com.formdev.flatlaf.util.SoftCache;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
import com.kitfox.svg.SVGDiagram;
|
import com.github.weisj.jsvg.SVGDocument;
|
||||||
import com.kitfox.svg.SVGException;
|
import com.github.weisj.jsvg.geometry.size.FloatSize;
|
||||||
import com.kitfox.svg.SVGUniverse;
|
import com.github.weisj.jsvg.parser.SVGLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An icon that loads and paints SVG.
|
* An icon that loads and paints SVG.
|
||||||
@@ -62,12 +62,9 @@ public class FlatSVGIcon
|
|||||||
extends ImageIcon
|
extends ImageIcon
|
||||||
implements DisabledIconProvider
|
implements DisabledIconProvider
|
||||||
{
|
{
|
||||||
// cache that uses soft references for values, which allows freeing SVG diagrams if no longer used
|
// cache that uses soft references for values, which allows freeing SVG documents if no longer used
|
||||||
private static final SoftCache<URI, SVGDiagram> svgCache = new SoftCache<>();
|
private static final SoftCache<String, SVGDocument> svgCache = new SoftCache<>();
|
||||||
|
private static final SVGLoader svgLoader = new SVGLoader();
|
||||||
// use own SVG universe so that it can not be cleared from anywhere
|
|
||||||
private static final SVGUniverse svgUniverse = new SVGUniverse();
|
|
||||||
private static int streamNumber;
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final int width;
|
private final int width;
|
||||||
@@ -75,11 +72,11 @@ public class FlatSVGIcon
|
|||||||
private final float scale;
|
private final float scale;
|
||||||
private final boolean disabled;
|
private final boolean disabled;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
private final URI uri;
|
private final URL url;
|
||||||
|
|
||||||
private ColorFilter colorFilter;
|
private ColorFilter colorFilter;
|
||||||
|
|
||||||
private SVGDiagram diagram;
|
private SVGDocument document;
|
||||||
private boolean dark;
|
private boolean dark;
|
||||||
private boolean loadFailed;
|
private boolean loadFailed;
|
||||||
|
|
||||||
@@ -220,7 +217,7 @@ public class FlatSVGIcon
|
|||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
public FlatSVGIcon( URL url ) {
|
public FlatSVGIcon( URL url ) {
|
||||||
this( null, -1, -1, 1, false, null, url2uri( url ) );
|
this( null, -1, -1, 1, false, null, url );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -236,7 +233,7 @@ public class FlatSVGIcon
|
|||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
public FlatSVGIcon( URI uri ) {
|
public FlatSVGIcon( URI uri ) {
|
||||||
this( null, -1, -1, 1, false, null, uri );
|
this( null, -1, -1, 1, false, null, uri2url( uri ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -251,7 +248,7 @@ public class FlatSVGIcon
|
|||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
public FlatSVGIcon( File file ) {
|
public FlatSVGIcon( File file ) {
|
||||||
this( null, -1, -1, 1, false, null, file.toURI() );
|
this( null, -1, -1, 1, false, null, uri2url( file.toURI() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -267,19 +264,15 @@ public class FlatSVGIcon
|
|||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
public FlatSVGIcon( InputStream in ) throws IOException {
|
public FlatSVGIcon( InputStream in ) throws IOException {
|
||||||
this( null, -1, -1, 1, false, null, loadFromStream( in ) );
|
this( null, -1, -1, 1, false, null, null );
|
||||||
|
|
||||||
// since the input stream is already loaded and parsed,
|
|
||||||
// get diagram here and remove it from cache
|
|
||||||
update();
|
|
||||||
synchronized( FlatSVGIcon.class ) {
|
|
||||||
svgCache.remove( uri );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static synchronized URI loadFromStream( InputStream in ) throws IOException {
|
|
||||||
try( InputStream in2 = in ) {
|
try( InputStream in2 = in ) {
|
||||||
return svgUniverse.loadSVG( in2, "/flatlaf-stream-" + (streamNumber++) );
|
document = svgLoader.load( in2 );
|
||||||
|
|
||||||
|
if( document == null ) {
|
||||||
|
loadFailed = true;
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: failed to load SVG icon from input stream", null );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,20 +284,22 @@ public class FlatSVGIcon
|
|||||||
* @since 2.0.1
|
* @since 2.0.1
|
||||||
*/
|
*/
|
||||||
public FlatSVGIcon( FlatSVGIcon icon ) {
|
public FlatSVGIcon( FlatSVGIcon icon ) {
|
||||||
this( icon.name, icon.width, icon.height, icon.scale, icon.disabled, icon.classLoader, icon.uri );
|
this( icon.name, icon.width, icon.height, icon.scale, icon.disabled, icon.classLoader, icon.url );
|
||||||
colorFilter = icon.colorFilter;
|
colorFilter = icon.colorFilter;
|
||||||
diagram = icon.diagram;
|
document = icon.document;
|
||||||
dark = icon.dark;
|
dark = icon.dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader, URI uri ) {
|
protected FlatSVGIcon( String name, int width, int height, float scale,
|
||||||
|
boolean disabled, ClassLoader classLoader, URL url )
|
||||||
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.disabled = disabled;
|
this.disabled = disabled;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.uri = uri;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -383,9 +378,9 @@ public class FlatSVGIcon
|
|||||||
if( width == this.width && height == this.height )
|
if( width == this.width && height == this.height )
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, url );
|
||||||
icon.colorFilter = colorFilter;
|
icon.colorFilter = colorFilter;
|
||||||
icon.diagram = diagram;
|
icon.document = document;
|
||||||
icon.dark = dark;
|
icon.dark = dark;
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
@@ -402,9 +397,9 @@ public class FlatSVGIcon
|
|||||||
if( scale == this.scale )
|
if( scale == this.scale )
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, url );
|
||||||
icon.colorFilter = colorFilter;
|
icon.colorFilter = colorFilter;
|
||||||
icon.diagram = diagram;
|
icon.document = document;
|
||||||
icon.dark = dark;
|
icon.dark = dark;
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
@@ -421,9 +416,9 @@ public class FlatSVGIcon
|
|||||||
if( disabled )
|
if( disabled )
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader, uri );
|
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader, url );
|
||||||
icon.colorFilter = colorFilter;
|
icon.colorFilter = colorFilter;
|
||||||
icon.diagram = diagram;
|
icon.document = document;
|
||||||
icon.dark = dark;
|
icon.dark = dark;
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
@@ -462,19 +457,19 @@ public class FlatSVGIcon
|
|||||||
if( loadFailed )
|
if( loadFailed )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( dark == isDarkLaf() && diagram != null )
|
if( dark == isDarkLaf() && document != null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dark = isDarkLaf();
|
dark = isDarkLaf();
|
||||||
|
|
||||||
// SVGs already loaded via url or input stream can not have light/dark variants
|
// SVGs already loaded via url, file or input stream can not have light/dark variants
|
||||||
if( uri != null && diagram != null )
|
if( document != null && name == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
URI uri = this.uri;
|
URL url = this.url;
|
||||||
if( uri == null ) {
|
if( url == null ) {
|
||||||
URL url = getIconURL( name, dark );
|
url = getIconURL( name, dark );
|
||||||
if( url == null & dark )
|
if( url == null && dark )
|
||||||
url = getIconURL( name, false );
|
url = getIconURL( name, false );
|
||||||
|
|
||||||
if( url == null ) {
|
if( url == null ) {
|
||||||
@@ -482,33 +477,30 @@ public class FlatSVGIcon
|
|||||||
LoggingFacade.INSTANCE.logConfig( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
LoggingFacade.INSTANCE.logConfig( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uri = url2uri( url );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
diagram = loadSVG( uri );
|
document = loadSVG( url );
|
||||||
loadFailed = (diagram == null);
|
loadFailed = (document == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized SVGDiagram loadSVG( URI uri ) {
|
static synchronized SVGDocument loadSVG( URL url ) {
|
||||||
// get from our cache
|
// get from our cache
|
||||||
SVGDiagram diagram = svgCache.get( uri );
|
String cacheKey = url.toString();
|
||||||
if( diagram != null )
|
SVGDocument document = svgCache.get( cacheKey );
|
||||||
return diagram;
|
if( document != null )
|
||||||
|
return document;
|
||||||
|
|
||||||
// load/get SVG diagram
|
// load SVG document
|
||||||
diagram = svgUniverse.getDiagram( uri );
|
document = svgLoader.load( url );
|
||||||
|
|
||||||
if( diagram == null ) {
|
if( document == null ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: failed to load '" + uri + "'", null );
|
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: failed to load '" + url + "'", null );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to our (soft) cache and remove from SVGUniverse (hard) cache
|
svgCache.put( cacheKey, document );
|
||||||
svgCache.put( uri, diagram );
|
|
||||||
svgUniverse.removeDocument( uri );
|
|
||||||
|
|
||||||
return diagram;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
private URL getIconURL( String name, boolean dark ) {
|
private URL getIconURL( String name, boolean dark ) {
|
||||||
@@ -528,7 +520,7 @@ public class FlatSVGIcon
|
|||||||
*/
|
*/
|
||||||
public boolean hasFound() {
|
public boolean hasFound() {
|
||||||
update();
|
update();
|
||||||
return diagram != null;
|
return document != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -540,7 +532,7 @@ public class FlatSVGIcon
|
|||||||
return scaleSize( width );
|
return scaleSize( width );
|
||||||
|
|
||||||
update();
|
update();
|
||||||
return scaleSize( (diagram != null) ? Math.round( diagram.getWidth() ) : 16 );
|
return scaleSize( (document != null) ? Math.round( document.size().width ) : 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -552,7 +544,7 @@ public class FlatSVGIcon
|
|||||||
return scaleSize( height );
|
return scaleSize( height );
|
||||||
|
|
||||||
update();
|
update();
|
||||||
return scaleSize( (diagram != null) ? Math.round( diagram.getHeight() ) : 16 );
|
return scaleSize( (document != null) ? Math.round( document.size().height ) : 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private int scaleSize( int size ) {
|
private int scaleSize( int size ) {
|
||||||
@@ -583,12 +575,7 @@ public class FlatSVGIcon
|
|||||||
Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), colorFilter, ColorFilter.getInstance(), grayFilter );
|
Graphics2D g2 = new GraphicsFilter( (Graphics2D) g.create(), colorFilter, ColorFilter.getInstance(), grayFilter );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// same hints as in FlatUIUtils.setRenderingHints()
|
setRenderingHints( g2 );
|
||||||
g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
|
|
||||||
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE );
|
|
||||||
|
|
||||||
// enable better image scaling
|
|
||||||
g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
|
|
||||||
|
|
||||||
paintSvg( g2, x, y );
|
paintSvg( g2, x, y );
|
||||||
} finally {
|
} finally {
|
||||||
@@ -597,7 +584,7 @@ public class FlatSVGIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void paintSvg( Graphics2D g, int x, int y ) {
|
private void paintSvg( Graphics2D g, int x, int y ) {
|
||||||
if( diagram == null ) {
|
if( document == null ) {
|
||||||
paintSvgError( g, x, y );
|
paintSvgError( g, x, y );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -607,19 +594,18 @@ public class FlatSVGIcon
|
|||||||
|
|
||||||
UIScale.scaleGraphics( g );
|
UIScale.scaleGraphics( g );
|
||||||
if( width > 0 || height > 0 ) {
|
if( width > 0 || height > 0 ) {
|
||||||
double sx = (width > 0) ? width / diagram.getWidth() : 1;
|
FloatSize svgSize = document.size();
|
||||||
double sy = (height > 0) ? height / diagram.getHeight() : 1;
|
double sx = (width > 0) ? width / svgSize.width : 1;
|
||||||
|
double sy = (height > 0) ? height / svgSize.height : 1;
|
||||||
if( sx != 1 || sy != 1 )
|
if( sx != 1 || sy != 1 )
|
||||||
g.scale( sx, sy );
|
g.scale( sx, sy );
|
||||||
}
|
}
|
||||||
if( scale != 1 )
|
if( scale != 1 )
|
||||||
g.scale( scale, scale );
|
g.scale( scale, scale );
|
||||||
|
|
||||||
diagram.setIgnoringClipHeuristic( true );
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
diagram.render( g );
|
document.render( null, g );
|
||||||
} catch( SVGException ex ) {
|
} catch( Exception ex ) {
|
||||||
paintSvgError( g, 0, 0 );
|
paintSvgError( g, 0, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,10 +648,21 @@ public class FlatSVGIcon
|
|||||||
return MultiResolutionImageSupport.create( 0, dimensions, producer );
|
return MultiResolutionImageSupport.create( 0, dimensions, producer );
|
||||||
}
|
}
|
||||||
|
|
||||||
static URI url2uri( URL url ) {
|
static void setRenderingHints( Graphics2D g ) {
|
||||||
|
// enable anti-aliasing
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
|
||||||
|
|
||||||
|
// disable coordinate normalization for correct line rendering
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
// enable better image scaling
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
|
||||||
|
}
|
||||||
|
|
||||||
|
static URL uri2url( URI uri ) {
|
||||||
try {
|
try {
|
||||||
return url.toURI();
|
return uri.toURL();
|
||||||
} catch( URISyntaxException ex ) {
|
} catch( MalformedURLException ex ) {
|
||||||
throw new IllegalArgumentException( ex );
|
throw new IllegalArgumentException( ex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -964,6 +961,18 @@ public class FlatSVGIcon
|
|||||||
this.grayFilter = grayFilter;
|
this.grayFilter = grayFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create() {
|
||||||
|
return new GraphicsFilter( (Graphics2D) super.create(),
|
||||||
|
colorFilter, globalColorFilter, grayFilter );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics create( int x, int y, int width, int height ) {
|
||||||
|
return new GraphicsFilter( (Graphics2D) super.create( x, y, width, height ),
|
||||||
|
colorFilter, globalColorFilter, grayFilter );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColor( Color c ) {
|
public void setColor( Color c ) {
|
||||||
super.setColor( filterColor( c ) );
|
super.setColor( filterColor( c ) );
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user