mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69851b7f3a | ||
|
|
92b53bf0df | ||
|
|
93e0496fd2 | ||
|
|
5151951f46 | ||
|
|
58dbccec2d | ||
|
|
90de14d013 | ||
|
|
5f961618bf | ||
|
|
37c375e2fa | ||
|
|
1758c175ed | ||
|
|
96f2a02cfa | ||
|
|
96d4bda6c8 | ||
|
|
02cf6050a1 | ||
|
|
38cf32a2e9 | ||
|
|
2ae7589d14 | ||
|
|
bcb2e1f0a1 | ||
|
|
14932d3f07 | ||
|
|
c3b9dc397d | ||
|
|
58b653f55d | ||
|
|
1dcdc42dde | ||
|
|
58a0a16985 | ||
|
|
a117243f14 | ||
|
|
22411060be | ||
|
|
045263ae58 | ||
|
|
024b6daaf6 | ||
|
|
bd5512c121 | ||
|
|
9afce83a02 | ||
|
|
07a8bd9486 | ||
|
|
bcdc0a8fce | ||
|
|
b295809432 | ||
|
|
52763ab932 | ||
|
|
99666265c9 | ||
|
|
af3e280d74 | ||
|
|
b57e4c0565 | ||
|
|
aca9931560 | ||
|
|
d09e166e4a | ||
|
|
68a7a60ff2 | ||
|
|
f21261914b | ||
|
|
7b11339fdc | ||
|
|
081fd43d98 | ||
|
|
ef2eedfc7c | ||
|
|
0dba9265be | ||
|
|
301aae9b8e | ||
|
|
c63f4e9662 | ||
|
|
47508dc6ac | ||
|
|
3a8879608a | ||
|
|
b221889549 | ||
|
|
c00d99b85f | ||
|
|
0bf87b753d | ||
|
|
53f2730064 | ||
|
|
d487c3b005 | ||
|
|
fef6ae7ff7 | ||
|
|
f6b42754de | ||
|
|
2ae9bb381d | ||
|
|
53bde84710 | ||
|
|
d006ac27ff | ||
|
|
c478d28b71 | ||
|
|
99f7b9ad84 | ||
|
|
ab58101ce3 | ||
|
|
d8f3682dc0 | ||
|
|
1fec7ba553 | ||
|
|
418f55f34e | ||
|
|
05d795b2ae | ||
|
|
a365b750d9 | ||
|
|
0aecfb565f | ||
|
|
0cf4edd9e5 | ||
|
|
dd7b7c6aef | ||
|
|
0bd677c46b | ||
|
|
1a131d5206 | ||
|
|
016e515ae2 | ||
|
|
456ceb3c58 | ||
|
|
2169be1b45 | ||
|
|
49eb0b0201 | ||
|
|
2e222bcdea | ||
|
|
c7fa475128 | ||
|
|
4174b065f3 | ||
|
|
df6256d989 | ||
|
|
c27db56321 | ||
|
|
97bed8554a | ||
|
|
751c0e16e9 | ||
|
|
936de60700 | ||
|
|
f6b64d48ec | ||
|
|
b043da7d4c | ||
|
|
7e47cc2443 | ||
|
|
b8b45f9442 | ||
|
|
66337f9af6 | ||
|
|
54646706a0 | ||
|
|
e8ee037d09 | ||
|
|
6d705e568a | ||
|
|
e768791eba | ||
|
|
2aff7c97f9 | ||
|
|
ca6fc7773e | ||
|
|
a1395a5490 | ||
|
|
61dd4d71d6 | ||
|
|
6beda53238 | ||
|
|
941441d7e1 | ||
|
|
d10ea41b47 | ||
|
|
9458870f70 | ||
|
|
095794bbd1 | ||
|
|
c7fc0aa936 | ||
|
|
a8d98ced61 | ||
|
|
831b3d851a | ||
|
|
8c891c7016 | ||
|
|
5c4706cbc9 | ||
|
|
db66a6c4f0 | ||
|
|
0517e4fc02 | ||
|
|
dd7fa4a87d | ||
|
|
e5956900ea | ||
|
|
3755593c14 | ||
|
|
8ddd3b6d68 | ||
|
|
840083940d | ||
|
|
0cdfd29ecf | ||
|
|
bb32c727b6 | ||
|
|
f978c04750 | ||
|
|
b6a504e121 | ||
|
|
5fae367fab | ||
|
|
6e807f44b2 | ||
|
|
53ebed7f89 | ||
|
|
1c10c41808 | ||
|
|
01170b669b | ||
|
|
b56215e5e3 | ||
|
|
221e801561 | ||
|
|
90edbe23d7 | ||
|
|
5b16a814c8 | ||
|
|
ef01721464 |
70
.github/workflows/ci.yml
vendored
70
.github/workflows/ci.yml
vendored
@@ -19,46 +19,32 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# test against
|
# test against
|
||||||
# - Java 1.8 (minimum requirement)
|
# - Java 8 (minimum requirement)
|
||||||
# - Java 9 (first version with JPMS)
|
|
||||||
# - Java LTS versions (11, 17, ...)
|
# - Java LTS versions (11, 17, ...)
|
||||||
# - lastest Java version(s)
|
# - lastest Java version(s)
|
||||||
java:
|
java:
|
||||||
- 1.8
|
- 8
|
||||||
- 9
|
|
||||||
- 11 # LTS
|
- 11 # LTS
|
||||||
- 14
|
- 17 # LTS
|
||||||
- 15
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
if: matrix.java == '1.8'
|
if: matrix.java == '8'
|
||||||
|
|
||||||
- name: Setup Java ${{ matrix.java }}
|
- name: Setup Java ${{ matrix.java }}
|
||||||
uses: actions/setup-java@v1
|
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
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
if: matrix.java == '11'
|
if: matrix.java == '11'
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-build-artifacts
|
name: FlatLaf-build-artifacts
|
||||||
@@ -77,25 +63,14 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: adopt # pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
- name: Publish snapshot to oss.sonatype.org
|
||||||
run: ./gradlew publish :flatlaf-theme-editor:build -Dorg.gradle.internal.publish.checksums.insecure=true
|
run: ./gradlew publish :flatlaf-theme-editor:build -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||||
@@ -124,25 +99,14 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: adopt # pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -Drelease=true
|
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -Drelease=true
|
||||||
|
|||||||
34
.github/workflows/natives.yml
vendored
34
.github/workflows/natives.yml
vendored
@@ -11,48 +11,40 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||||
- '.github/workflows/natives.yml'
|
- '.github/workflows/natives.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
paths:
|
paths:
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||||
- '.github/workflows/natives.yml'
|
- '.github/workflows/natives.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Windows:
|
Windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
|
|
||||||
- name: Setup Java 1.8
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 1.8
|
java-version: 11
|
||||||
|
distribution: adopt
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
!~/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew :flatlaf-natives-windows:build
|
# --no-daemon is necessary on Windows otherwise caching Gradle would fail with:
|
||||||
|
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||||
|
run: ./gradlew :flatlaf-natives-windows:build-natives --no-daemon
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-natives-windows-build-artifacts
|
name: FlatLaf-natives-windows-build-artifacts
|
||||||
path: |
|
path: |
|
||||||
|
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives
|
||||||
flatlaf-natives/flatlaf-natives-windows/build
|
flatlaf-natives/flatlaf-natives-windows/build
|
||||||
|
|||||||
141
CHANGELOG.md
141
CHANGELOG.md
@@ -1,6 +1,145 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
## 2.3
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- FileChooser: Added (optional) shortcuts panel. On Windows it contains "Recent
|
||||||
|
Items", "Desktop", "Documents", "This PC" and "Network". On macOS and Linux it
|
||||||
|
is empty/hidden. (issue #100)
|
||||||
|
- Button and ToggleButton: Added missing foreground colors for hover, pressed,
|
||||||
|
focused and selected states. (issue #535)
|
||||||
|
- Table: Optionally paint alternating rows below table if table is smaller than
|
||||||
|
scroll pane. Set UI value `Table.paintOutsideAlternateRows` to `true`.
|
||||||
|
Requires that `Table.alternateRowColor` is set to a color. (issue #504)
|
||||||
|
- ToggleButton: Made the underline placement of tab-style toggle buttons
|
||||||
|
configurable. (PR #530; issue #529)
|
||||||
|
- Added spanish translation. (PR #525)
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- IntelliJ Themes: Fixed `TitledBorder` text color in "Monokai Pro" theme.
|
||||||
|
(issue #524)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.2
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- SplitPane: Allow limiting one-touch expanding to a single side (set client
|
||||||
|
property `JSplitPane.expandableSide` to `"left"` or `"right"`). (issue #355)
|
||||||
|
- TabbedPane: Selected tab underline color now changes depending on whether the
|
||||||
|
focus is within the tab content. (issue #398)
|
||||||
|
- IntelliJ Themes:
|
||||||
|
- Added "Monokai Pro" and "Xcode-Dark" themes.
|
||||||
|
- TabbedPane now use different background color for selected tabs in all "Arc"
|
||||||
|
themes, in "Hiberbee Dark" and in all "Material UI Lite" themes.
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- Native window decorations (Windows 10/11 only): Fixed wrong window title
|
||||||
|
character encoding used in Windows taskbar. (issue #502)
|
||||||
|
- Button: Fixed icon layout and preferred width of default buttons that use bold
|
||||||
|
font. (issue #506)
|
||||||
|
- FileChooser: Enabled full row selection for details view to fix alternate row
|
||||||
|
coloring. (issue #512)
|
||||||
|
- SplitPane: Fixed `StackOverflowError` caused by layout loop that may occur
|
||||||
|
under special circumstances. (issue #513)
|
||||||
|
- Table: Slightly changed grid colors to make grid better recognizable. (issue
|
||||||
|
#514)
|
||||||
|
- ToolBar: Fixed endless loop in focus navigation that may occur under special
|
||||||
|
circumstances. (issue #505)
|
||||||
|
- IntelliJ Themes: `Component.accentColor` UI property now has useful theme
|
||||||
|
specific values. (issue #507)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.1
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- Menus: Improved usability of submenus. (PR #490; issue #247)
|
||||||
|
- Menus: Scroll large menus using mouse wheel or up/down arrows. (issue #225)
|
||||||
|
- Linux: Support using custom window decorations. Enable with
|
||||||
|
`JFrame.setDefaultLookAndFeelDecorated(true)` and
|
||||||
|
`JDialog.setDefaultLookAndFeelDecorated(true)` before creating a window.
|
||||||
|
(issue #482)
|
||||||
|
- ScrollBar: Added UI value `ScrollBar.minimumButtonSize` to specify minimum
|
||||||
|
scroll arrow button size (if shown). (issue #493)
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
|
- PasswordField: Fixed reveal button appearance in IntelliJ themes. (issue #494)
|
||||||
|
- ScrollBar: Center and scale arrows in scroll up/down buttons (if shown).
|
||||||
|
(issue #493)
|
||||||
|
- TextArea, TextPane and EditorPane: No longer select all text when component is
|
||||||
|
focused for the first time. (issue #498; regression in FlatLaf 2.0)
|
||||||
|
- TabbedPane: Disable all items in "Show Hidden Tabs" popup menu if tabbed pane
|
||||||
|
is disabled.
|
||||||
|
|
||||||
|
#### Incompatibilities
|
||||||
|
|
||||||
|
- Method `FlatUIUtils.paintArrow()` (and class `FlatArrowButton`) now paints
|
||||||
|
arrows one pixel smaller than before. To fix this, increase parameter
|
||||||
|
`arrowSize` by one.
|
||||||
|
|
||||||
|
|
||||||
|
## 2.0.2
|
||||||
|
|
||||||
|
- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on
|
||||||
|
HiDPI screens when dragging window partly offscreen and back into screen
|
||||||
|
bounds. (issue #477)
|
||||||
|
- Repaint component when setting client property `JComponent.outline` (issue
|
||||||
|
#480).
|
||||||
|
- macOS: Fixed NPE when using some icons in main menu items. (issue #483)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.0.1
|
||||||
|
|
||||||
|
- Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471;
|
||||||
|
regression in FlatLaf 2.0)
|
||||||
|
- ToolTip: Fixed wrong tooltip location if component overrides
|
||||||
|
`JComponent.getToolTipLocation()` and wants place tooltip under mouse
|
||||||
|
location. (issue #468)
|
||||||
|
- Extras: Added copy constructor to `FlatSVGIcon`. (issue #465)
|
||||||
|
- Moved `module-info.class` from `META-INF\versions\9\` to root folder of JARs.
|
||||||
|
(issue #466)
|
||||||
|
|
||||||
|
|
||||||
|
## 2.0
|
||||||
|
|
||||||
|
- Added system property `flatlaf.nativeLibraryPath` to load native libraries
|
||||||
|
from a directory. (PR #453)
|
||||||
|
- Fixed "endless recursion in font" exception in
|
||||||
|
`FlatLaf$ActiveFont.createValue()` if `UIManager.getFont()` is invoked from
|
||||||
|
multiple threads. (issue #456)
|
||||||
|
- PasswordField: Preserve reveal button state when switching theme. (PR #442;
|
||||||
|
issue #173)
|
||||||
|
- PasswordField: Reveal button did not show password if
|
||||||
|
`JPasswordField.setEchoChar()` was invoked from application. (PR #442; issue
|
||||||
|
#173)
|
||||||
|
- Slider: Fixed/improved focused indicator color when changing accent color. (PR
|
||||||
|
#375)
|
||||||
|
- TextField:
|
||||||
|
- Improved hover/pressed/selected colors of leading/trailing buttons (e.g.
|
||||||
|
"reveal" button in password field). (issue #452)
|
||||||
|
- Clear button no longer paints over round border. (issue #451)
|
||||||
|
- Extras: Fixed concurrent loading of SVG icons on multiple threads. (issue
|
||||||
|
#459)
|
||||||
|
- Use FlatLaf native window decorations by default when running in
|
||||||
|
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki)
|
||||||
|
(instead of using JetBrains custom decorations). System variable
|
||||||
|
`flatlaf.useJetBrainsCustomDecorations` is now `false` by default (was `true`
|
||||||
|
in FlatLaf 1.x). (issue #454)
|
||||||
|
- Native window decorations:
|
||||||
|
- Fixed blurry iconify/maximize/close button hover rectangles at 125%, 150% or
|
||||||
|
175% scaling. (issue #431)
|
||||||
|
- Updated maximize and restore icons for Windows 11 style. (requires Java
|
||||||
|
8u321, 11.0.14, 17.0.2 or 18+)
|
||||||
|
- Updated hover and pressed colors of iconify/maximize/close buttons for
|
||||||
|
Windows 11 style.
|
||||||
|
|
||||||
|
|
||||||
## 2.0-rc1
|
## 2.0-rc1
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
@@ -24,7 +163,7 @@ FlatLaf Change Log
|
|||||||
- Possibility to hide window title bar icon (for single window set client
|
- Possibility to hide window title bar icon (for single window set client
|
||||||
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
||||||
value `TitlePane.showIcon` to `false`).
|
value `TitlePane.showIcon` to `false`).
|
||||||
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
|
- OptionPane: Hide window title bar icon by default. Can be made visibly by
|
||||||
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
||||||
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
||||||
(issue #416)
|
(issue #416)
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -11,9 +11,9 @@ scales on **HiDPI** displays and runs on Java 8 or newer.
|
|||||||
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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
IntelliJ Platform Themes
|
IntelliJ Platform Themes
|
||||||
@@ -99,10 +99,22 @@ For more information and documentation visit
|
|||||||
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
||||||
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
||||||
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
||||||
|
- [Components UI Properties](https://www.formdev.com/flatlaf/components/)
|
||||||
|
- [Typography](https://www.formdev.com/flatlaf/typography/)
|
||||||
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
||||||
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
||||||
|
|
||||||
|
|
||||||
|
Theme Editor
|
||||||
|
------------
|
||||||
|
|
||||||
|
The Theme Editor that supports editing FlatLaf theme properties files. See
|
||||||
|
[Theme Editor documentation](https://www.formdev.com/flatlaf/theme-editor/) for
|
||||||
|
details and downloads.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
Buzz
|
Buzz
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -114,6 +126,11 @@ Buzz
|
|||||||
Applications using FlatLaf
|
Applications using FlatLaf
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
-  [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 -
|
-  [Jailer](https://github.com/Wisser/Jailer) 11.2 -
|
||||||
database subsetting and relational data browsing tool
|
database subsetting and relational data browsing tool
|
||||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
||||||
@@ -149,9 +166,10 @@ Applications using FlatLaf
|
|||||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||||
checks your website
|
checks your website
|
||||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||||
game
|
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5+ - a sci-fi tabletop
|
||||||
|
BattleTech simulator suite handling battles, unit building, and campaigns
|
||||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||||
0.13.b024 - GUI builder for
|
0.13.b024 - GUI builder for
|
||||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val releaseVersion = "2.0-rc1"
|
val releaseVersion = "2.3"
|
||||||
val developmentVersion = "2.0-SNAPSHOT"
|
val developmentVersion = "2.4-SNAPSHOT"
|
||||||
|
|
||||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
add( "java9Compile", sourceSets.main.get().output )
|
add( "java9Implementation", sourceSets.main.get().output )
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|||||||
@@ -63,11 +63,9 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
|||||||
jar {
|
jar {
|
||||||
manifest.attributes( "Multi-Release" to "true" )
|
manifest.attributes( "Multi-Release" to "true" )
|
||||||
|
|
||||||
into( "META-INF/versions/9" ) {
|
|
||||||
from( sourceSets["module-info"].output ) {
|
from( sourceSets["module-info"].output ) {
|
||||||
include( "module-info.class" )
|
include( "module-info.class" )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -43,11 +43,6 @@ tasks {
|
|||||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
|
||||||
// build native libraries
|
|
||||||
dependsOn( ":flatlaf-natives-windows:assemble" )
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName.set( "flatlaf" )
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Signature file v4.1
|
#Signature file v4.1
|
||||||
#Version 1.6
|
#Version 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"
|
||||||
@@ -30,7 +30,12 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY = "JTextFiel
|
|||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
|
||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
||||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
||||||
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
|
||||||
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
|
||||||
|
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
|
||||||
fld public final static java.lang.String SQUARE_SIZE = "JButton.squareSize"
|
fld public final static java.lang.String SQUARE_SIZE = "JButton.squareSize"
|
||||||
|
fld public final static java.lang.String STYLE = "FlatLaf.style"
|
||||||
|
fld public final static java.lang.String STYLE_CLASS = "FlatLaf.styleClass"
|
||||||
fld public final static java.lang.String TABBED_PANE_ALIGN_CENTER = "center"
|
fld public final static java.lang.String TABBED_PANE_ALIGN_CENTER = "center"
|
||||||
fld public final static java.lang.String TABBED_PANE_ALIGN_FILL = "fill"
|
fld public final static java.lang.String TABBED_PANE_ALIGN_FILL = "fill"
|
||||||
fld public final static java.lang.String TABBED_PANE_ALIGN_LEADING = "leading"
|
fld public final static java.lang.String TABBED_PANE_ALIGN_LEADING = "leading"
|
||||||
@@ -59,6 +64,9 @@ fld public final static java.lang.String TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT = "JT
|
|||||||
fld public final static java.lang.String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"
|
fld public final static java.lang.String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement"
|
fld public final static java.lang.String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement"
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets"
|
fld public final static java.lang.String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets"
|
||||||
|
fld public final static java.lang.String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType"
|
||||||
|
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_CARD = "card"
|
||||||
|
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined"
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE = "JTabbedPane.tabWidthMode"
|
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE = "JTabbedPane.tabWidthMode"
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_COMPACT = "compact"
|
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_COMPACT = "compact"
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_EQUAL = "equal"
|
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_EQUAL = "equal"
|
||||||
@@ -67,12 +75,20 @@ fld public final static java.lang.String TABBED_PANE_TRAILING_COMPONENT = "JTabb
|
|||||||
fld public final static java.lang.String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground"
|
fld public final static java.lang.String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground"
|
||||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_COLOR = "JToggleButton.tab.underlineColor"
|
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_COLOR = "JToggleButton.tab.underlineColor"
|
||||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_HEIGHT = "JToggleButton.tab.underlineHeight"
|
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_HEIGHT = "JToggleButton.tab.underlineHeight"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon"
|
||||||
fld public final static java.lang.String TEXT_FIELD_PADDING = "JTextField.padding"
|
fld public final static java.lang.String TEXT_FIELD_PADDING = "JTextField.padding"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent"
|
||||||
|
fld public final static java.lang.String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon"
|
||||||
fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground"
|
fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground"
|
||||||
fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"
|
fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"
|
||||||
|
fld public final static java.lang.String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon"
|
||||||
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"
|
||||||
|
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)
|
||||||
meth public static int clientPropertyInt(javax.swing.JComponent,java.lang.String,int)
|
meth public static int clientPropertyInt(javax.swing.JComponent,java.lang.String,int)
|
||||||
@@ -165,6 +181,7 @@ meth public boolean isSupportedLookAndFeel()
|
|||||||
meth public final boolean equals(java.lang.Object)
|
meth public final boolean equals(java.lang.Object)
|
||||||
meth public final int hashCode()
|
meth public final int hashCode()
|
||||||
meth public java.lang.String getID()
|
meth public java.lang.String getID()
|
||||||
|
meth public java.util.Map<java.lang.String,java.lang.String> getExtraDefaults()
|
||||||
meth public javax.swing.Icon getDisabledIcon(javax.swing.JComponent,javax.swing.Icon)
|
meth public javax.swing.Icon getDisabledIcon(javax.swing.JComponent,javax.swing.Icon)
|
||||||
meth public javax.swing.UIDefaults getDefaults()
|
meth public javax.swing.UIDefaults getDefaults()
|
||||||
meth public static boolean install(javax.swing.LookAndFeel)
|
meth public static boolean install(javax.swing.LookAndFeel)
|
||||||
@@ -174,6 +191,8 @@ meth public static boolean isShowMnemonics()
|
|||||||
meth public static boolean isUseNativeWindowDecorations()
|
meth public static boolean isUseNativeWindowDecorations()
|
||||||
meth public static boolean setup(javax.swing.LookAndFeel)
|
meth public static boolean setup(javax.swing.LookAndFeel)
|
||||||
meth public static boolean supportsNativeWindowDecorations()
|
meth public static boolean supportsNativeWindowDecorations()
|
||||||
|
meth public static java.lang.Object parseDefaultsValue(java.lang.String,java.lang.String,java.lang.Class<?>)
|
||||||
|
meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults()
|
||||||
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
|
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
|
||||||
meth public static void hideMnemonics()
|
meth public static void hideMnemonics()
|
||||||
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
||||||
@@ -181,22 +200,26 @@ meth public static void installLafInfo(java.lang.String,java.lang.Class<? extend
|
|||||||
meth public static void registerCustomDefaultsSource(java.io.File)
|
meth public static void registerCustomDefaultsSource(java.io.File)
|
||||||
meth public static void registerCustomDefaultsSource(java.lang.String)
|
meth public static void registerCustomDefaultsSource(java.lang.String)
|
||||||
meth public static void registerCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
meth public static void registerCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||||
|
meth public static void registerCustomDefaultsSource(java.net.URL)
|
||||||
meth public static void repaintAllFramesAndDialogs()
|
meth public static void repaintAllFramesAndDialogs()
|
||||||
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
||||||
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
||||||
|
meth public static void setGlobalExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||||
meth public static void setUseNativeWindowDecorations(boolean)
|
meth public static void setUseNativeWindowDecorations(boolean)
|
||||||
meth public static void showMnemonics(java.awt.Component)
|
meth public static void showMnemonics(java.awt.Component)
|
||||||
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
||||||
meth public static void unregisterCustomDefaultsSource(java.lang.String)
|
meth public static void unregisterCustomDefaultsSource(java.lang.String)
|
||||||
meth public static void unregisterCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
meth public static void unregisterCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||||
|
meth public static void unregisterCustomDefaultsSource(java.net.URL)
|
||||||
meth public static void updateUI()
|
meth public static void updateUI()
|
||||||
meth public static void updateUILater()
|
meth public static void updateUILater()
|
||||||
meth public void initialize()
|
meth public void initialize()
|
||||||
meth public void registerUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
meth public void registerUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||||
|
meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||||
meth public void uninitialize()
|
meth public void uninitialize()
|
||||||
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||||
supr javax.swing.plaf.basic.BasicLookAndFeel
|
supr javax.swing.plaf.basic.BasicLookAndFeel
|
||||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,mnemonicHandler,oldPopupFactory,postInitialization,uiDefaultsGetters,updateUIPending
|
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,subMenuUsabilityHelper,uiDefaultsGetters,updateUIPending
|
||||||
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
||||||
|
|
||||||
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
||||||
@@ -231,6 +254,7 @@ hfds baseTheme,dark,name,properties
|
|||||||
CLSS public abstract interface com.formdev.flatlaf.FlatSystemProperties
|
CLSS public abstract interface com.formdev.flatlaf.FlatSystemProperties
|
||||||
fld public final static java.lang.String ANIMATION = "flatlaf.animation"
|
fld public final static java.lang.String ANIMATION = "flatlaf.animation"
|
||||||
fld public final static java.lang.String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded"
|
fld public final static java.lang.String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded"
|
||||||
|
fld public final static java.lang.String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath"
|
||||||
fld public final static java.lang.String UI_SCALE = "flatlaf.uiScale"
|
fld public final static java.lang.String UI_SCALE = "flatlaf.uiScale"
|
||||||
fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown"
|
fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown"
|
||||||
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"
|
||||||
@@ -330,7 +354,15 @@ innr public static HSLIncreaseDecrease
|
|||||||
innr public static Mix
|
innr public static Mix
|
||||||
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
||||||
meth public static float clamp(float)
|
meth public static float clamp(float)
|
||||||
|
meth public static float luma(java.awt.Color)
|
||||||
|
meth public static java.awt.Color darken(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color desaturate(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color lighten(java.awt.Color,float)
|
||||||
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color saturate(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color shade(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color spin(java.awt.Color,float)
|
||||||
|
meth public static java.awt.Color tint(java.awt.Color,float)
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|
||||||
CLSS public abstract interface static com.formdev.flatlaf.util.ColorFunctions$ColorFunction
|
CLSS public abstract interface static com.formdev.flatlaf.util.ColorFunctions$ColorFunction
|
||||||
@@ -566,6 +598,7 @@ meth public static java.util.List<java.awt.Image> getResolutionVariants(java.awt
|
|||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
||||||
|
cons public init(java.io.File,boolean)
|
||||||
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
||||||
meth public boolean isLoaded()
|
meth public boolean isLoaded()
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
@@ -589,18 +622,52 @@ meth public void paintIcon(java.awt.Component,java.awt.Graphics,int,int)
|
|||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
hfds iconHeight,iconWidth,imageIcon,lastImage,lastSystemScaleFactor,lastUserScaleFactor
|
hfds iconHeight,iconWidth,imageIcon,lastImage,lastSystemScaleFactor,lastUserScaleFactor
|
||||||
|
|
||||||
|
CLSS public com.formdev.flatlaf.util.SoftCache<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||||
|
cons public init()
|
||||||
|
cons public init(int)
|
||||||
|
intf java.util.Map<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>
|
||||||
|
meth public boolean containsKey(java.lang.Object)
|
||||||
|
meth public boolean containsValue(java.lang.Object)
|
||||||
|
meth public boolean isEmpty()
|
||||||
|
meth public int size()
|
||||||
|
meth public java.util.Collection<{com.formdev.flatlaf.util.SoftCache%1}> values()
|
||||||
|
meth public java.util.Set<java.util.Map$Entry<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>> entrySet()
|
||||||
|
meth public java.util.Set<{com.formdev.flatlaf.util.SoftCache%0}> keySet()
|
||||||
|
meth public void clear()
|
||||||
|
meth public void forEach(java.util.function.BiConsumer<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||||
|
meth public void putAll(java.util.Map<? extends {com.formdev.flatlaf.util.SoftCache%0},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||||
|
meth public void replaceAll(java.util.function.BiFunction<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||||
|
meth public {com.formdev.flatlaf.util.SoftCache%1} get(java.lang.Object)
|
||||||
|
meth public {com.formdev.flatlaf.util.SoftCache%1} put({com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1})
|
||||||
|
meth public {com.formdev.flatlaf.util.SoftCache%1} remove(java.lang.Object)
|
||||||
|
supr java.lang.Object
|
||||||
|
hfds map,queue
|
||||||
|
hcls CacheReference
|
||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.StringUtils
|
CLSS public com.formdev.flatlaf.util.StringUtils
|
||||||
cons public init()
|
cons public init()
|
||||||
meth public static boolean isEmpty(java.lang.String)
|
meth public static boolean isEmpty(java.lang.String)
|
||||||
|
meth public static boolean isTrimmedEmpty(java.lang.String)
|
||||||
meth public static java.lang.String removeLeading(java.lang.String,java.lang.String)
|
meth public static java.lang.String removeLeading(java.lang.String,java.lang.String)
|
||||||
meth public static java.lang.String removeTrailing(java.lang.String,java.lang.String)
|
meth public static java.lang.String removeTrailing(java.lang.String,java.lang.String)
|
||||||
|
meth public static java.lang.String substringTrimmed(java.lang.String,int)
|
||||||
|
meth public static java.lang.String substringTrimmed(java.lang.String,int,int)
|
||||||
meth public static java.util.List<java.lang.String> split(java.lang.String,char)
|
meth public static java.util.List<java.lang.String> split(java.lang.String,char)
|
||||||
|
meth public static java.util.List<java.lang.String> split(java.lang.String,char,boolean,boolean)
|
||||||
|
supr java.lang.Object
|
||||||
|
|
||||||
|
CLSS public com.formdev.flatlaf.util.SwingUtils
|
||||||
|
cons public init()
|
||||||
|
meth public static <%0 extends java.awt.Component> {%%0} getComponentByName(java.awt.Container,java.lang.String)
|
||||||
supr java.lang.Object
|
supr java.lang.Object
|
||||||
|
|
||||||
CLSS public com.formdev.flatlaf.util.SystemInfo
|
CLSS public com.formdev.flatlaf.util.SystemInfo
|
||||||
cons public init()
|
cons public init()
|
||||||
|
fld public final static boolean isAARCH64
|
||||||
fld public final static boolean isJava_11_orLater
|
fld public final static boolean isJava_11_orLater
|
||||||
fld public final static boolean isJava_15_orLater
|
fld public final static boolean isJava_15_orLater
|
||||||
|
fld public final static boolean isJava_17_orLater
|
||||||
|
fld public final static boolean isJava_18_orLater
|
||||||
fld public final static boolean isJava_9_orLater
|
fld public final static boolean isJava_9_orLater
|
||||||
fld public final static boolean isJetBrainsJVM
|
fld public final static boolean isJetBrainsJVM
|
||||||
fld public final static boolean isJetBrainsJVM_11_orLater
|
fld public final static boolean isJetBrainsJVM_11_orLater
|
||||||
@@ -615,6 +682,8 @@ fld public final static boolean isWebswing
|
|||||||
fld public final static boolean isWinPE
|
fld public final static boolean isWinPE
|
||||||
fld public final static boolean isWindows
|
fld public final static boolean isWindows
|
||||||
fld public final static boolean isWindows_10_orLater
|
fld public final static boolean isWindows_10_orLater
|
||||||
|
fld public final static boolean isWindows_11_orLater
|
||||||
|
fld public final static boolean isX86
|
||||||
fld public final static boolean isX86_64
|
fld public final static boolean isX86_64
|
||||||
fld public final static long javaVersion
|
fld public final static long javaVersion
|
||||||
fld public final static long osVersion
|
fld public final static long osVersion
|
||||||
@@ -627,6 +696,7 @@ cons public init()
|
|||||||
meth public static boolean isSystemScalingEnabled()
|
meth public static boolean isSystemScalingEnabled()
|
||||||
meth public static double getSystemScaleFactor(java.awt.Graphics2D)
|
meth public static double getSystemScaleFactor(java.awt.Graphics2D)
|
||||||
meth public static double getSystemScaleFactor(java.awt.GraphicsConfiguration)
|
meth public static double getSystemScaleFactor(java.awt.GraphicsConfiguration)
|
||||||
|
meth public static float computeFontScaleFactor(java.awt.Font)
|
||||||
meth public static float getUserScaleFactor()
|
meth public static float getUserScaleFactor()
|
||||||
meth public static float scale(float)
|
meth public static float scale(float)
|
||||||
meth public static float unscale(float)
|
meth public static float unscale(float)
|
||||||
@@ -933,6 +1003,34 @@ CLSS public abstract interface !annotation java.lang.annotation.Target
|
|||||||
intf java.lang.annotation.Annotation
|
intf java.lang.annotation.Annotation
|
||||||
meth public abstract java.lang.annotation.ElementType[] value()
|
meth public abstract java.lang.annotation.ElementType[] value()
|
||||||
|
|
||||||
|
CLSS public abstract interface java.util.Map<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||||
|
innr public abstract interface static Entry
|
||||||
|
meth public abstract boolean containsKey(java.lang.Object)
|
||||||
|
meth public abstract boolean containsValue(java.lang.Object)
|
||||||
|
meth public abstract boolean equals(java.lang.Object)
|
||||||
|
meth public abstract boolean isEmpty()
|
||||||
|
meth public abstract int hashCode()
|
||||||
|
meth public abstract int size()
|
||||||
|
meth public abstract java.util.Collection<{java.util.Map%1}> values()
|
||||||
|
meth public abstract java.util.Set<java.util.Map$Entry<{java.util.Map%0},{java.util.Map%1}>> entrySet()
|
||||||
|
meth public abstract java.util.Set<{java.util.Map%0}> keySet()
|
||||||
|
meth public abstract void clear()
|
||||||
|
meth public abstract void putAll(java.util.Map<? extends {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||||
|
meth public abstract {java.util.Map%1} get(java.lang.Object)
|
||||||
|
meth public abstract {java.util.Map%1} put({java.util.Map%0},{java.util.Map%1})
|
||||||
|
meth public abstract {java.util.Map%1} remove(java.lang.Object)
|
||||||
|
meth public boolean remove(java.lang.Object,java.lang.Object)
|
||||||
|
meth public boolean replace({java.util.Map%0},{java.util.Map%1},{java.util.Map%1})
|
||||||
|
meth public void forEach(java.util.function.BiConsumer<? super {java.util.Map%0},? super {java.util.Map%1}>)
|
||||||
|
meth public void replaceAll(java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||||
|
meth public {java.util.Map%1} compute({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||||
|
meth public {java.util.Map%1} computeIfAbsent({java.util.Map%0},java.util.function.Function<? super {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||||
|
meth public {java.util.Map%1} computeIfPresent({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||||
|
meth public {java.util.Map%1} getOrDefault(java.lang.Object,{java.util.Map%1})
|
||||||
|
meth public {java.util.Map%1} merge({java.util.Map%0},{java.util.Map%1},java.util.function.BiFunction<? super {java.util.Map%1},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||||
|
meth public {java.util.Map%1} putIfAbsent({java.util.Map%0},{java.util.Map%1})
|
||||||
|
meth public {java.util.Map%1} replace({java.util.Map%0},{java.util.Map%1})
|
||||||
|
|
||||||
CLSS public abstract interface javax.swing.Icon
|
CLSS public abstract interface javax.swing.Icon
|
||||||
meth public abstract int getIconHeight()
|
meth public abstract int getIconHeight()
|
||||||
meth public abstract int getIconWidth()
|
meth public abstract int getIconWidth()
|
||||||
|
|||||||
@@ -391,6 +391,40 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||||
|
|
||||||
|
//---- JSplitPane ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what side of the spilt pane is allowed to expand
|
||||||
|
* via one-touch expanding arrow buttons.
|
||||||
|
* Requires that one-touch expanding is enabled with
|
||||||
|
* {@link javax.swing.JSplitPane#setOneTouchExpandable(boolean)}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JSplitPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_LEFT} or
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_RIGHT}
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only left/top side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only right/bottom side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
||||||
|
|
||||||
//---- JTabbedPane --------------------------------------------------------
|
//---- JTabbedPane --------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -874,7 +908,26 @@ public interface FlatClientProperties
|
|||||||
* The component should be not opaque because the text field border is painted
|
* The component should be not opaque because the text field border is painted
|
||||||
* slightly inside the usually visible border in some cases.
|
* slightly inside the usually visible border in some cases.
|
||||||
* E.g. when focused (in some themes) or when an outline color is specified
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
* (see {@link #OUTLINE}.
|
* (see {@link #OUTLINE}).
|
||||||
|
* <p>
|
||||||
|
* The component is prepared in the following way:
|
||||||
|
* <ul>
|
||||||
|
* <li>Component client property {@link #STYLE_CLASS} is set to {@code inTextField}.
|
||||||
|
* <li>If component is a button or toggle button, client property {@link #BUTTON_TYPE}
|
||||||
|
* is set to {@link #BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||||
|
* and button cursor is set to default cursor (if not set).
|
||||||
|
* <li>If component is a toolbar, client property {@link #STYLE_CLASS}
|
||||||
|
* is set to {@code inTextField} on all toolbar children
|
||||||
|
* and toolbar cursor is set to default cursor (if not set).
|
||||||
|
* </ul>
|
||||||
|
* Because text fields use the text cursor by default and the cursor is inherited by child components,
|
||||||
|
* it may be necessary to explicitly set component cursor if you e.g. need the default arrow cursor.
|
||||||
|
* E.g. {@code comp.setCursor( Cursor.getDefaultCursor() )}.
|
||||||
|
* <p>
|
||||||
|
* Styling is used to modify insets/margins and appearance of buttons and toolbars
|
||||||
|
* so that they fit nicely into the text field and do not increase text field height.
|
||||||
|
* See styles {@code [style]Button.inTextField} and {@code [style]ToolBar.inTextField}
|
||||||
|
* in {@code Flat[Light|Dark]Laf.properties}.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
@@ -886,15 +939,7 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
* <p>
|
* <p>
|
||||||
* The component will be positioned inside and aligned to the visible text field border.
|
* See {@link #TEXT_FIELD_LEADING_COMPONENT} for details.
|
||||||
* There is no gap between the visible border and the component.
|
|
||||||
* The laid out component size will be the preferred component width
|
|
||||||
* and the inner text field height.
|
|
||||||
* <p>
|
|
||||||
* The component should be not opaque because the text field border is painted
|
|
||||||
* slightly inside the usually visible border in some cases.
|
|
||||||
* E.g. when focused (in some themes) or when an outline color is specified
|
|
||||||
* (see {@link #OUTLINE}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
@@ -947,7 +992,22 @@ public interface FlatClientProperties
|
|||||||
//---- JToggleButton ------------------------------------------------------
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
* Placement of underline if toggle button type is {@link #BUTTON_TYPE_TAB}
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||||
|
* <strong>SupportedValues:</strong>
|
||||||
|
* {@link SwingConstants#BOTTOM} (default)
|
||||||
|
* {@link SwingConstants#TOP},
|
||||||
|
* {@link SwingConstants#LEFT} or
|
||||||
|
* {@link SwingConstants#RIGHT}
|
||||||
|
*
|
||||||
|
* @since 2.3
|
||||||
|
*/
|
||||||
|
String TAB_BUTTON_UNDERLINE_PLACEMENT = "JToggleButton.tab.underlinePlacement";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thickness of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
|||||||
* Allows loading of additional .properties files from addon JARs.
|
* Allows loading of additional .properties files from addon JARs.
|
||||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||||
* <p>
|
* <p>
|
||||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
* If you extend this class in an addon JAR, you also have to add a text file named
|
||||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||||
* to the addon JAR. The file must contain a single line with the class name.
|
* to the addon JAR. The file must contain a single line with the class name.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority used to sort addon loading.
|
* Returns the priority used to sort addon loading.
|
||||||
* The order is only important if you want overwrite UI defaults of other addons.
|
* The order is only important if you want to overwrite UI defaults of other addons.
|
||||||
* Lower numbers mean higher priority.
|
* Lower numbers mean higher priority.
|
||||||
* Returns 10000 by default.
|
* Returns 10000 by default.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
|||||||
/**
|
/**
|
||||||
* Default color palette for action icons and object icons.
|
* Default color palette for action icons and object icons.
|
||||||
* <p>
|
* <p>
|
||||||
* The idea is to use only this well defined set of colors in SVG icons and
|
* The idea is to use only this well-defined set of colors in SVG icons, and
|
||||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
|||||||
* <p>
|
* <p>
|
||||||
* You may use these colors also in your application (outside of SVG icons), but do
|
* You may use these colors also in your application (outside of SVG icons), but do
|
||||||
* not use the RGB values defined in this enum.<br>
|
* not use the RGB values defined in this enum.<br>
|
||||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ class FlatInputMaps
|
|||||||
//---- class LazyInputMapEx -----------------------------------------------
|
//---- class LazyInputMapEx -----------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates a input map.
|
* Lazily creates an input map.
|
||||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||||
*/
|
*/
|
||||||
private static class LazyInputMapEx
|
private static class LazyInputMapEx
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ public abstract class FlatLaf
|
|||||||
|
|
||||||
private PopupFactory oldPopupFactory;
|
private PopupFactory oldPopupFactory;
|
||||||
private MnemonicHandler mnemonicHandler;
|
private MnemonicHandler mnemonicHandler;
|
||||||
|
private SubMenuUsabilityHelper subMenuUsabilityHelper;
|
||||||
|
|
||||||
private Consumer<UIDefaults> postInitialization;
|
private Consumer<UIDefaults> postInitialization;
|
||||||
private List<Function<Object, Object>> uiDefaultsGetters;
|
private List<Function<Object, Object>> uiDefaultsGetters;
|
||||||
@@ -166,18 +167,19 @@ public abstract class FlatLaf
|
|||||||
* Returns whether FlatLaf supports custom window decorations.
|
* Returns whether FlatLaf supports custom window decorations.
|
||||||
* This depends on the operating system and on the used Java runtime.
|
* This depends on the operating system and on the used Java runtime.
|
||||||
* <p>
|
* <p>
|
||||||
* This method returns {@code true} on Windows 10 (see exception below), {@code false} otherwise.
|
* This method returns {@code true} on Windows 10/11 (see exception below)
|
||||||
|
* and on Linux, {@code false} otherwise.
|
||||||
* <p>
|
* <p>
|
||||||
* Returns also {@code false} on Windows 10 if:
|
* Returns also {@code false} on Windows 10/11 if:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>FlatLaf native window border support is available (requires Windows 10)</li>
|
* <li>FlatLaf native window border support is available (requires Windows 10/11)</li>
|
||||||
* <li>running in
|
* <li>running in
|
||||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime 11 (or later)</a>
|
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime 11 (or later)</a>
|
||||||
* (<a href="https://github.com/JetBrains/JetBrainsRuntime">source code on github</a>)
|
* (<a href="https://github.com/JetBrains/JetBrainsRuntime">source code on github</a>)
|
||||||
* and JBR supports custom window decorations
|
* and JBR supports custom window decorations
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* In this cases, custom decorations are enabled by the root pane.
|
* In these cases, custom decorations are enabled by the root pane.
|
||||||
* Usage of {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} or
|
* Usage of {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} or
|
||||||
* {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} is not necessary.
|
* {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} is not necessary.
|
||||||
*/
|
*/
|
||||||
@@ -190,7 +192,7 @@ public abstract class FlatLaf
|
|||||||
FlatNativeWindowBorder.isSupported() )
|
FlatNativeWindowBorder.isSupported() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return SystemInfo.isWindows_10_orLater;
|
return SystemInfo.isWindows_10_orLater || SystemInfo.isLinux;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -243,6 +245,10 @@ public abstract class FlatLaf
|
|||||||
mnemonicHandler = new MnemonicHandler();
|
mnemonicHandler = new MnemonicHandler();
|
||||||
mnemonicHandler.install();
|
mnemonicHandler.install();
|
||||||
|
|
||||||
|
// install submenu usability helper
|
||||||
|
subMenuUsabilityHelper = new SubMenuUsabilityHelper();
|
||||||
|
subMenuUsabilityHelper.install();
|
||||||
|
|
||||||
// listen to desktop property changes to update UI if system font or scaling changes
|
// listen to desktop property changes to update UI if system font or scaling changes
|
||||||
if( SystemInfo.isWindows ) {
|
if( SystemInfo.isWindows ) {
|
||||||
// Windows 10 allows increasing font size independent of scaling:
|
// Windows 10 allows increasing font size independent of scaling:
|
||||||
@@ -322,6 +328,12 @@ public abstract class FlatLaf
|
|||||||
mnemonicHandler = null;
|
mnemonicHandler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uninstall submenu usability helper
|
||||||
|
if( subMenuUsabilityHelper != null ) {
|
||||||
|
subMenuUsabilityHelper.uninstall();
|
||||||
|
subMenuUsabilityHelper = null;
|
||||||
|
}
|
||||||
|
|
||||||
// restore default link color
|
// restore default link color
|
||||||
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
|
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
|
||||||
postInitialization = null;
|
postInitialization = null;
|
||||||
@@ -605,7 +617,7 @@ public abstract class FlatLaf
|
|||||||
uiFont = ((ActiveFont)defaultFont).derive( baseFont, fontSize -> {
|
uiFont = ((ActiveFont)defaultFont).derive( baseFont, fontSize -> {
|
||||||
return Math.round( fontSize * UIScale.computeFontScaleFactor( baseFont ) );
|
return Math.round( fontSize * UIScale.computeFontScaleFactor( baseFont ) );
|
||||||
} );
|
} );
|
||||||
};
|
}
|
||||||
|
|
||||||
// increase font size if system property "flatlaf.uiScale" is set
|
// increase font size if system property "flatlaf.uiScale" is set
|
||||||
uiFont = UIScale.applyCustomScaleFactor( uiFont );
|
uiFont = UIScale.applyCustomScaleFactor( uiFont );
|
||||||
@@ -760,7 +772,7 @@ public abstract class FlatLaf
|
|||||||
* Invoke this method before setting the look and feel.
|
* Invoke this method before setting the look and feel.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package must be opened in {@code module-info.java}.
|
* If using Java modules, the package must be opened in {@code module-info.java}.
|
||||||
* Otherwise use {@link #registerCustomDefaultsSource(URL)}.
|
* Otherwise, use {@link #registerCustomDefaultsSource(URL)}.
|
||||||
*
|
*
|
||||||
* @param packageName a package name (e.g. "com.myapp.resources")
|
* @param packageName a package name (e.g. "com.myapp.resources")
|
||||||
*/
|
*/
|
||||||
@@ -862,7 +874,7 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
@@ -894,7 +906,7 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The extra defaults are useful for smaller additional defaults that may change.
|
* The extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
@@ -951,7 +963,7 @@ public abstract class FlatLaf
|
|||||||
// re-set current LaF
|
// re-set current LaF
|
||||||
UIManager.setLookAndFeel( lookAndFeel );
|
UIManager.setLookAndFeel( lookAndFeel );
|
||||||
|
|
||||||
// must fire property change events ourself because old and new LaF are the same
|
// must fire property change events ourselves because old and new LaF are the same
|
||||||
PropertyChangeEvent e = new PropertyChangeEvent( UIManager.class, "lookAndFeel", lookAndFeel, lookAndFeel );
|
PropertyChangeEvent e = new PropertyChangeEvent( UIManager.class, "lookAndFeel", lookAndFeel, lookAndFeel );
|
||||||
for( PropertyChangeListener l : UIManager.getPropertyChangeListeners() )
|
for( PropertyChangeListener l : UIManager.getPropertyChangeListeners() )
|
||||||
l.propertyChange( e );
|
l.propertyChange( e );
|
||||||
@@ -995,7 +1007,7 @@ public abstract class FlatLaf
|
|||||||
/**
|
/**
|
||||||
* Returns whether native window decorations are supported on current platform.
|
* Returns whether native window decorations are supported on current platform.
|
||||||
* <p>
|
* <p>
|
||||||
* This requires Windows 10, but may be disabled if running in special environments
|
* This requires Windows 10/11, but may be disabled if running in special environments
|
||||||
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
|
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
|
||||||
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
|
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
|
||||||
* {@code false}, then this method also returns {@code false}.
|
* {@code false}, then this method also returns {@code false}.
|
||||||
@@ -1223,6 +1235,9 @@ public abstract class FlatLaf
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Object getValue( Object key ) {
|
private Object getValue( Object key ) {
|
||||||
|
// use local variable for getters to avoid potential multi-threading issues
|
||||||
|
List<Function<Object, Object>> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters;
|
||||||
|
|
||||||
if( uiDefaultsGetters == null )
|
if( uiDefaultsGetters == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1276,8 +1291,9 @@ public abstract class FlatLaf
|
|||||||
this.scaleSize = scaleSize;
|
this.scaleSize = scaleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// using synchronized to avoid exception if invoked at the same time on multiple threads
|
||||||
@Override
|
@Override
|
||||||
public Object createValue( UIDefaults table ) {
|
public synchronized Object createValue( UIDefaults table ) {
|
||||||
if( inCreateValue )
|
if( inCreateValue )
|
||||||
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public interface FlatSystemProperties
|
|||||||
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||||
* which has the same syntax as this one.
|
* which has the same syntax as this one.
|
||||||
* <p>
|
* <p>
|
||||||
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
|
* Since FlatLaf 1.1.2: Scale factors less than 100% are allowed.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||||
*/
|
*/
|
||||||
@@ -81,7 +81,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||||
* UI default {@code TitlePane.useWindowDecorations}.
|
* UI default {@code TitlePane.useWindowDecorations}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -92,16 +92,16 @@ public interface FlatSystemProperties
|
|||||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||||
* when creating {@code JFrame} or {@code JDialog}.
|
* when creating {@code JFrame} or {@code JDialog}.
|
||||||
* Requires that the application runs in a
|
* Requires that the application runs in a
|
||||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
|
* <a href="https://github.com/JetBrains/JetBrainsRuntime/wiki">JetBrains Runtime</a>
|
||||||
* (based on OpenJDK).
|
* (based on OpenJDK).
|
||||||
* <p>
|
* <p>
|
||||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||||
* Then FlatLaf native window decorations are used.
|
* Then FlatLaf native window decorations are used.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> {@code true}
|
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||||
*/
|
*/
|
||||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Window 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -139,6 +139,15 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a directory in which the native FlatLaf library have been extracted.
|
||||||
|
* The path can be absolute or relative to current application working directory.
|
||||||
|
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a system property is set and returns {@code true} if its value
|
* Checks whether a system property is set and returns {@code true} if its value
|
||||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.formdev.flatlaf.json.ParseException;
|
|||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
||||||
@@ -162,8 +163,11 @@ public class IntelliJTheme
|
|||||||
applyCheckBoxColors( defaults );
|
applyCheckBoxColors( defaults );
|
||||||
|
|
||||||
// copy values
|
// copy values
|
||||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
Object value = defaults.get( e.getValue() );
|
||||||
|
if( value != null )
|
||||||
|
defaults.put( e.getKey(), value );
|
||||||
|
}
|
||||||
|
|
||||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||||
Object panelBackground = defaults.get( "Panel.background" );
|
Object panelBackground = defaults.get( "Panel.background" );
|
||||||
@@ -175,7 +179,7 @@ public class IntelliJTheme
|
|||||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||||
|
|
||||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
// IDEA uses an SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||||
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
||||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
||||||
if( helpButtonBackground == null )
|
if( helpButtonBackground == null )
|
||||||
@@ -242,7 +246,19 @@ public class IntelliJTheme
|
|||||||
defaults.put( "Tree.rowHeight", 22 );
|
defaults.put( "Tree.rowHeight", 22 );
|
||||||
|
|
||||||
// apply theme specific UI defaults at the end to allow overwriting
|
// apply theme specific UI defaults at the end to allow overwriting
|
||||||
defaults.putAll( themeSpecificDefaults );
|
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||||
|
Object key = e.getKey();
|
||||||
|
Object value = e.getValue();
|
||||||
|
|
||||||
|
// append styles to existing styles
|
||||||
|
if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
|
||||||
|
Object oldValue = defaults.get( key );
|
||||||
|
if( oldValue != null )
|
||||||
|
value = oldValue + "; " + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaults.put( key, value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||||
@@ -299,8 +315,19 @@ public class IntelliJTheme
|
|||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
||||||
if( value instanceof Map ) {
|
if( value instanceof Map ) {
|
||||||
for( Map.Entry<String, Object> e : ((Map<String, Object>)value).entrySet() )
|
Map<String, Object> map = (Map<String, Object>)value;
|
||||||
|
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
||||||
|
String osKey = SystemInfo.isWindows ? "os.windows"
|
||||||
|
: SystemInfo.isMacOS ? "os.mac"
|
||||||
|
: SystemInfo.isLinux ? "os.linux" : null;
|
||||||
|
if( osKey != null && map.containsKey( osKey ) )
|
||||||
|
apply( key, map.get( osKey ), defaults, defaultsKeysCache, uiKeys );
|
||||||
|
else if( map.containsKey( "os.default" ) )
|
||||||
|
apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys );
|
||||||
|
} else {
|
||||||
|
for( Map.Entry<String, Object> e : map.entrySet() )
|
||||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if( "".equals( value ) )
|
if( "".equals( value ) )
|
||||||
return; // ignore empty value
|
return; // ignore empty value
|
||||||
@@ -534,12 +561,12 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Rename UI default keys (key --> value). */
|
/** Rename UI default keys (key --> value). */
|
||||||
private static 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 Map<String, String> uiKeyCopying = new HashMap<>();
|
private static final Map<String, String> uiKeyCopying = new HashMap<>();
|
||||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// ComboBox
|
// ComboBox
|
||||||
@@ -600,6 +627,11 @@ public class IntelliJTheme
|
|||||||
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
|
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
|
||||||
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||||
|
|
||||||
|
// TabbedPane
|
||||||
|
uiKeyCopying.put( "TabbedPane.selectedBackground", "DefaultTabs.underlinedTabBackground" );
|
||||||
|
uiKeyCopying.put( "TabbedPane.selectedForeground", "DefaultTabs.underlinedTabForeground" );
|
||||||
|
uiKeyCopying.put( "TabbedPane.inactiveUnderlineColor", "DefaultTabs.inactiveUnderlineColor" );
|
||||||
|
|
||||||
// TitlePane
|
// TitlePane
|
||||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
||||||
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class LinuxFontPolicy
|
|||||||
|
|
||||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||||
if( value instanceof Integer ) {
|
if( value instanceof Integer ) {
|
||||||
int dpi = ((Integer)value).intValue() / 1024;
|
int dpi = (Integer) value / 1024;
|
||||||
if( dpi == -1 )
|
if( dpi == -1 )
|
||||||
dpi = 96;
|
dpi = 96;
|
||||||
if( dpi < 50 )
|
if( dpi < 50 )
|
||||||
@@ -197,7 +197,7 @@ class LinuxFontPolicy
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default font for KDE for KDE configuration files.
|
* Gets the default font for KDE from KDE configuration files.
|
||||||
*
|
*
|
||||||
* The Swing fonts are not updated when the user changes system font size
|
* The Swing fonts are not updated when the user changes system font size
|
||||||
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
||||||
@@ -278,7 +278,7 @@ 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 FileReader( file ) ) ) {
|
||||||
String line = null;
|
String line;
|
||||||
while( (line = reader.readLine()) != null )
|
while( (line = reader.readLine()) != null )
|
||||||
lines.add( line );
|
lines.add( line );
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
|
|||||||
@@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.awt.AWTEvent;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.MouseInfo;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.PointerInfo;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLayeredPane;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.MenuElement;
|
||||||
|
import javax.swing.MenuSelectionManager;
|
||||||
|
import javax.swing.RootPaneContainer;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improves usability of submenus by using a
|
||||||
|
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||||
|
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
class SubMenuUsabilityHelper
|
||||||
|
implements ChangeListener
|
||||||
|
{
|
||||||
|
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||||
|
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||||
|
|
||||||
|
private SubMenuEventQueue subMenuEventQueue;
|
||||||
|
private SafeTrianglePainter safeTrianglePainter;
|
||||||
|
private boolean changePending;
|
||||||
|
|
||||||
|
// mouse location in screen coordinates
|
||||||
|
private int mouseX;
|
||||||
|
private int mouseY;
|
||||||
|
|
||||||
|
// target popup bounds in screen coordinates
|
||||||
|
private int targetX;
|
||||||
|
private int targetTopY;
|
||||||
|
private int targetBottomY;
|
||||||
|
|
||||||
|
private Rectangle invokerBounds;
|
||||||
|
|
||||||
|
void install() {
|
||||||
|
MenuSelectionManager.defaultManager().addChangeListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
MenuSelectionManager.defaultManager().removeChangeListener( this );
|
||||||
|
uninstallEventQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// handle menu selection change later, but only once in case of temporary changes
|
||||||
|
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||||
|
// 1. old menu item is removed from menu selection
|
||||||
|
// 2. new menu item is added to menu selection
|
||||||
|
synchronized( this ) {
|
||||||
|
if( changePending )
|
||||||
|
return;
|
||||||
|
changePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
synchronized( this ) {
|
||||||
|
changePending = false;
|
||||||
|
}
|
||||||
|
menuSelectionChanged();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void menuSelectionChanged() {
|
||||||
|
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
System.out.println( "--- " + path.length );
|
||||||
|
for( int i = 0; i < path.length; i++ )
|
||||||
|
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||||
|
debug*/
|
||||||
|
|
||||||
|
// find submenu in menu selection
|
||||||
|
int subMenuIndex = findSubMenu( path );
|
||||||
|
|
||||||
|
// uninstall if there is no submenu in selection
|
||||||
|
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current mouse location
|
||||||
|
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||||
|
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||||
|
mouseX = mouseLocation.x;
|
||||||
|
mouseY = mouseLocation.y;
|
||||||
|
|
||||||
|
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||||
|
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||||
|
if( !popup.isShowing() ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get invoker screen bounds
|
||||||
|
Component invoker = popup.getInvoker();
|
||||||
|
invokerBounds = (invoker != null)
|
||||||
|
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// check whether mouse location is within invoker
|
||||||
|
if( invokerBounds != null && !invokerBounds.contains( mouseX, mouseY ) ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute top/bottom target locations
|
||||||
|
Point popupLocation = popup.getLocationOnScreen();
|
||||||
|
Dimension popupSize = popup.getSize();
|
||||||
|
targetX = (mouseX < popupLocation.x + (popupSize.width / 2))
|
||||||
|
? popupLocation.x
|
||||||
|
: popupLocation.x + popupSize.width;
|
||||||
|
targetTopY = popupLocation.y;
|
||||||
|
targetBottomY = popupLocation.y + popupSize.height;
|
||||||
|
|
||||||
|
// install own event queue to supress mouse events when mouse is moved within safe triangle
|
||||||
|
if( subMenuEventQueue == null )
|
||||||
|
subMenuEventQueue = new SubMenuEventQueue();
|
||||||
|
|
||||||
|
// create safe triangle painter
|
||||||
|
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||||
|
safeTrianglePainter = new SafeTrianglePainter( popup );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uninstallEventQueue() {
|
||||||
|
if( subMenuEventQueue != null ) {
|
||||||
|
subMenuEventQueue.uninstall();
|
||||||
|
subMenuEventQueue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null ) {
|
||||||
|
safeTrianglePainter.uninstall();
|
||||||
|
safeTrianglePainter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findSubMenu( MenuElement[] path ) {
|
||||||
|
for( int i = path.length - 1; i >= 1; i-- ) {
|
||||||
|
if( path[i] instanceof JPopupMenu &&
|
||||||
|
path[i - 1] instanceof JMenu &&
|
||||||
|
!((JMenu)path[i - 1]).isTopLevelMenu() )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Polygon createSafeTriangle() {
|
||||||
|
return new Polygon(
|
||||||
|
new int[] { mouseX, targetX, targetX },
|
||||||
|
new int[] { mouseY, targetTopY, targetBottomY },
|
||||||
|
3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class SubMenuEventQueue --------------------------------------------
|
||||||
|
|
||||||
|
private class SubMenuEventQueue
|
||||||
|
extends EventQueue
|
||||||
|
{
|
||||||
|
private Timer mouseUpdateTimer;
|
||||||
|
private Timer timeoutTimer;
|
||||||
|
|
||||||
|
private int newMouseX;
|
||||||
|
private int newMouseY;
|
||||||
|
private AWTEvent lastMouseEvent;
|
||||||
|
|
||||||
|
SubMenuEventQueue() {
|
||||||
|
// timer used to slightly delay update of mouse location used for safe triangle
|
||||||
|
mouseUpdateTimer = new Timer( 50, e -> {
|
||||||
|
mouseX = newMouseX;
|
||||||
|
mouseY = newMouseY;
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null )
|
||||||
|
safeTrianglePainter.repaint();
|
||||||
|
} );
|
||||||
|
mouseUpdateTimer.setRepeats( false );
|
||||||
|
|
||||||
|
// timer used to timeout safe triangle when mouse stops moving
|
||||||
|
timeoutTimer = new Timer( 200, e -> {
|
||||||
|
if( invokerBounds != null && !invokerBounds.contains( newMouseX, newMouseY ) ) {
|
||||||
|
// post last mouse event, which selects menu item at mouse location
|
||||||
|
if( lastMouseEvent != null ) {
|
||||||
|
postEvent( lastMouseEvent );
|
||||||
|
lastMouseEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
timeoutTimer.setRepeats( false );
|
||||||
|
|
||||||
|
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
mouseUpdateTimer.stop();
|
||||||
|
mouseUpdateTimer = null;
|
||||||
|
|
||||||
|
timeoutTimer.stop();
|
||||||
|
timeoutTimer = null;
|
||||||
|
|
||||||
|
lastMouseEvent = null;
|
||||||
|
|
||||||
|
super.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatchEvent( AWTEvent e ) {
|
||||||
|
int id = e.getID();
|
||||||
|
|
||||||
|
if( e instanceof MouseEvent &&
|
||||||
|
(id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED) )
|
||||||
|
{
|
||||||
|
newMouseX = ((MouseEvent)e).getXOnScreen();
|
||||||
|
newMouseY = ((MouseEvent)e).getYOnScreen();
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null )
|
||||||
|
safeTrianglePainter.repaint();
|
||||||
|
|
||||||
|
mouseUpdateTimer.stop();
|
||||||
|
timeoutTimer.stop();
|
||||||
|
|
||||||
|
// check whether mouse moved within safe triangle
|
||||||
|
if( createSafeTriangle().contains( newMouseX, newMouseY ) ) {
|
||||||
|
// update mouse location delayed (this changes the safe triangle)
|
||||||
|
mouseUpdateTimer.start();
|
||||||
|
|
||||||
|
timeoutTimer.start();
|
||||||
|
|
||||||
|
// remember last mouse event, which will be posted if the mouse stops moving
|
||||||
|
lastMouseEvent = e;
|
||||||
|
|
||||||
|
// ignore mouse event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update mouse location immediately (this changes the safe triangle)
|
||||||
|
mouseX = newMouseX;
|
||||||
|
mouseY = newMouseY;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.dispatchEvent( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class SafeTrianglePainter ------------------------------------------
|
||||||
|
|
||||||
|
private class SafeTrianglePainter
|
||||||
|
extends JComponent
|
||||||
|
{
|
||||||
|
SafeTrianglePainter( JPopupMenu popup ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( popup.getInvoker() );
|
||||||
|
if( window instanceof RootPaneContainer ) {
|
||||||
|
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||||
|
setSize( layeredPane.getSize() );
|
||||||
|
layeredPane.add( this, new Integer( JLayeredPane.POPUP_LAYER + 1 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
Container parent = getParent();
|
||||||
|
if( parent != null ) {
|
||||||
|
parent.remove( this );
|
||||||
|
parent.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent( Graphics g ) {
|
||||||
|
Point locationOnScreen = getLocationOnScreen();
|
||||||
|
g.translate( -locationOnScreen.x, -locationOnScreen.y );
|
||||||
|
|
||||||
|
g.setColor( Color.red );
|
||||||
|
((Graphics2D)g).draw( createSafeTriangle() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -350,7 +350,7 @@ class UIDefaultsLoader
|
|||||||
enum ValueType { UNKNOWN, STRING, BOOLEAN, CHARACTER, INTEGER, INTEGERORFLOAT, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR, FONT,
|
enum ValueType { UNKNOWN, STRING, BOOLEAN, CHARACTER, INTEGER, INTEGERORFLOAT, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR, FONT,
|
||||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER, NULL, LAZY }
|
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER, NULL, LAZY }
|
||||||
|
|
||||||
private static ValueType[] tempResultValueType = new ValueType[1];
|
private static final ValueType[] tempResultValueType = new ValueType[1];
|
||||||
private static Map<Class<?>, ValueType> javaValueTypes;
|
private static Map<Class<?>, ValueType> javaValueTypes;
|
||||||
private static Map<String, ValueType> knownValueTypes;
|
private static Map<String, ValueType> knownValueTypes;
|
||||||
|
|
||||||
@@ -466,6 +466,10 @@ class UIDefaultsLoader
|
|||||||
if( knownValueTypes == null ) {
|
if( knownValueTypes == null ) {
|
||||||
// create lazy
|
// create lazy
|
||||||
knownValueTypes = new HashMap<>();
|
knownValueTypes = new HashMap<>();
|
||||||
|
// system colors
|
||||||
|
knownValueTypes.put( "activeCaptionBorder", ValueType.COLOR );
|
||||||
|
knownValueTypes.put( "inactiveCaptionBorder", ValueType.COLOR );
|
||||||
|
knownValueTypes.put( "windowBorder", ValueType.COLOR );
|
||||||
// SplitPane
|
// SplitPane
|
||||||
knownValueTypes.put( "SplitPane.dividerSize", ValueType.INTEGER );
|
knownValueTypes.put( "SplitPane.dividerSize", ValueType.INTEGER );
|
||||||
knownValueTypes.put( "SplitPaneDivider.gripDotSize", ValueType.INTEGER );
|
knownValueTypes.put( "SplitPaneDivider.gripDotSize", ValueType.INTEGER );
|
||||||
@@ -780,6 +784,7 @@ class UIDefaultsLoader
|
|||||||
case "tint": return parseColorMix( "#fff", params, resolver, reportError );
|
case "tint": return parseColorMix( "#fff", params, resolver, reportError );
|
||||||
case "shade": return parseColorMix( "#000", params, resolver, reportError );
|
case "shade": return parseColorMix( "#000", params, resolver, reportError );
|
||||||
case "contrast": return parseColorContrast( params, resolver, reportError );
|
case "contrast": return parseColorContrast( params, resolver, reportError );
|
||||||
|
case "over": return parseColorOver( params, resolver, reportError );
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
parseColorDepth--;
|
parseColorDepth--;
|
||||||
@@ -792,7 +797,7 @@ class UIDefaultsLoader
|
|||||||
* Syntax: if(condition,trueValue,falseValue)
|
* Syntax: if(condition,trueValue,falseValue)
|
||||||
* <p>
|
* <p>
|
||||||
* This "if" function is only used if the "if" is passed as parameter to another
|
* This "if" function is only used if the "if" is passed as parameter to another
|
||||||
* color function. Otherwise the general "if" function is used.
|
* color function. Otherwise, the general "if" function is used.
|
||||||
*/
|
*/
|
||||||
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||||
if( params.size() != 3 )
|
if( params.size() != 3 )
|
||||||
@@ -847,7 +852,7 @@ class UIDefaultsLoader
|
|||||||
int lightness = parsePercentage( params.get( 2 ) );
|
int lightness = parsePercentage( params.get( 2 ) );
|
||||||
int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100;
|
int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100;
|
||||||
|
|
||||||
float[] hsl = new float[] { hue, saturation, lightness };
|
float[] hsl = { hue, saturation, lightness };
|
||||||
return new ColorUIResource( HSLColor.toRGB( hsl, alpha / 100f ) );
|
return new ColorUIResource( HSLColor.toRGB( hsl, alpha / 100f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,21 +907,32 @@ class UIDefaultsLoader
|
|||||||
* Syntax: fade(color,amount[,options])
|
* Syntax: fade(color,amount[,options])
|
||||||
* - color: a color (e.g. #f00) or a color function
|
* - color: a color (e.g. #f00) or a color function
|
||||||
* - amount: percentage 0-100%
|
* - amount: percentage 0-100%
|
||||||
* - options: [derived]
|
* - options: [derived] [lazy]
|
||||||
*/
|
*/
|
||||||
private static Object parseColorFade( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
private static Object parseColorFade( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||||
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;
|
||||||
|
boolean lazy = false;
|
||||||
|
|
||||||
if( params.size() > 2 ) {
|
if( params.size() > 2 ) {
|
||||||
String options = params.get( 2 );
|
String options = params.get( 2 );
|
||||||
derived = options.contains( "derived" );
|
derived = options.contains( "derived" );
|
||||||
|
lazy = options.contains( "lazy" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// create function
|
// create function
|
||||||
ColorFunction function = new ColorFunctions.Fade( amount );
|
ColorFunction function = new ColorFunctions.Fade( amount );
|
||||||
|
|
||||||
|
if( lazy ) {
|
||||||
|
return (LazyValue) t -> {
|
||||||
|
Object color = lazyUIManagerGet( colorStr );
|
||||||
|
return (color instanceof Color)
|
||||||
|
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// parse base color, apply function and create derived color
|
// parse base color, apply function and create derived color
|
||||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
||||||
}
|
}
|
||||||
@@ -1030,6 +1046,33 @@ class UIDefaultsLoader
|
|||||||
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError );
|
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syntax: over(foreground,background)
|
||||||
|
* - foreground: a foreground color (e.g. #f00) or a color function;
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
private static Object parseColorOver( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||||
|
String foregroundStr = params.get( 0 );
|
||||||
|
String backgroundStr = params.get( 1 );
|
||||||
|
|
||||||
|
// parse foreground color
|
||||||
|
ColorUIResource foreground = (ColorUIResource) parseColorOrFunction( resolver.apply( foregroundStr ), resolver, reportError );
|
||||||
|
if( foreground == null || foreground.getAlpha() == 255 )
|
||||||
|
return foreground;
|
||||||
|
|
||||||
|
Color foreground2 = new Color( foreground.getRGB() );
|
||||||
|
|
||||||
|
// parse background color
|
||||||
|
ColorUIResource background = (ColorUIResource) parseColorOrFunction( resolver.apply( backgroundStr ), resolver, reportError );
|
||||||
|
if( background == null )
|
||||||
|
return foreground2;
|
||||||
|
|
||||||
|
// create new color
|
||||||
|
float weight = foreground.getAlpha() / 255f;
|
||||||
|
return new ColorUIResource( ColorFunctions.mix( foreground2, background, weight ) );
|
||||||
|
}
|
||||||
|
|
||||||
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
|
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
|
||||||
boolean derived, Function<String, String> resolver, boolean reportError )
|
boolean derived, Function<String, String> resolver, boolean reportError )
|
||||||
{
|
{
|
||||||
@@ -1198,7 +1241,7 @@ class UIDefaultsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
Integer integer = parseInteger( value, true );
|
Integer integer = parseInteger( value, true );
|
||||||
if( integer.intValue() < min || integer.intValue() > max )
|
if( integer < min || integer > max )
|
||||||
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
||||||
return integer;
|
return integer;
|
||||||
}
|
}
|
||||||
@@ -1239,28 +1282,28 @@ class UIDefaultsLoader
|
|||||||
|
|
||||||
private static ActiveValue parseScaledInteger( String value ) {
|
private static ActiveValue parseScaledInteger( String value ) {
|
||||||
int val = parseInteger( value, true );
|
int val = parseInteger( value, true );
|
||||||
return (ActiveValue) t -> {
|
return t -> {
|
||||||
return UIScale.scale( val );
|
return UIScale.scale( val );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledFloat( String value ) {
|
private static ActiveValue parseScaledFloat( String value ) {
|
||||||
float val = parseFloat( value, true );
|
float val = parseFloat( value, true );
|
||||||
return (ActiveValue) t -> {
|
return t -> {
|
||||||
return UIScale.scale( val );
|
return UIScale.scale( val );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledInsets( String value ) {
|
private static ActiveValue parseScaledInsets( String value ) {
|
||||||
Insets insets = parseInsets( value );
|
Insets insets = parseInsets( value );
|
||||||
return (ActiveValue) t -> {
|
return t -> {
|
||||||
return UIScale.scale( insets );
|
return UIScale.scale( insets );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActiveValue parseScaledDimension( String value ) {
|
private static ActiveValue parseScaledDimension( String value ) {
|
||||||
Dimension dimension = parseDimension( value );
|
Dimension dimension = parseDimension( value );
|
||||||
return (ActiveValue) t -> {
|
return t -> {
|
||||||
return UIScale.scale( dimension );
|
return UIScale.scale( dimension );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
|||||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for animated icons that scales width and height, creates and initializes
|
* Base class for animated icons that scale width and height, creates and initializes
|
||||||
* a scaled graphics context for icon painting.
|
* a scaled graphics context for icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses do not need to scale icon painting.
|
* Subclasses do not need to scale icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* This class does not store any state information (needed for animation) in its instance.
|
* This class does not store any state information (needed for animation) in its instance.
|
||||||
* Instead a client property is set on the painted component.
|
* Instead, a client property is set on the painted component.
|
||||||
* This makes it possible to use a share icon instance for multiple components.
|
* This makes it possible to use a share icon instance for multiple components.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class FlatAscendingSortIcon
|
|||||||
boolean chevron = this.chevron;
|
boolean chevron = this.chevron;
|
||||||
Color sortIconColor = this.sortIconColor;
|
Color sortIconColor = this.sortIconColor;
|
||||||
|
|
||||||
// Because this icons are always shared for all table headers,
|
// Because this icon is always shared for all table headers,
|
||||||
// get icon specific style from FlatTableHeaderUI.
|
// get icon specific style from FlatTableHeaderUI.
|
||||||
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
||||||
if( tableHeader != null ) {
|
if( tableHeader != null ) {
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ public class FlatHelpButtonIcon
|
|||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
boolean enabled = c.isEnabled();
|
boolean enabled = c == null || c.isEnabled();
|
||||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
|
|
||||||
float xy = 0.5f;
|
float xy = 0.5f;
|
||||||
float wh = iconSize() - 1;
|
float wh = iconSize() - 1;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class FlatMenuArrowIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
if( !c.getComponentOrientation().isLeftToRight() )
|
if( c != null && !c.getComponentOrientation().isLeftToRight() )
|
||||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||||
|
|
||||||
g.setColor( getArrowColor( c ) );
|
g.setColor( getArrowColor( c ) );
|
||||||
@@ -82,7 +82,7 @@ public class FlatMenuArrowIcon
|
|||||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||||
return selectionForeground;
|
return selectionForeground;
|
||||||
|
|
||||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isUnderlineSelection() {
|
protected boolean isUnderlineSelection() {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class FlatTreeCollapsedIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because this icons are always shared for all trees,
|
* Because this icon is always shared for all trees,
|
||||||
* get icon specific style from FlatTreeUI.
|
* get icon specific style from FlatTreeUI.
|
||||||
*/
|
*/
|
||||||
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
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;
|
||||||
@@ -65,8 +66,14 @@ public abstract class FlatWindowAbstractIcon
|
|||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g ) {
|
||||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||||
if( background != null ) {
|
if( background != null ) {
|
||||||
|
// disable antialiasing for background rectangle painting to avoid blury edges when scaled (e.g. at 125% or 175%)
|
||||||
|
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||||
|
|
||||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||||
g.fillRect( 0, 0, width, height );
|
g.fillRect( 0, 0, width, height );
|
||||||
|
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.geom.Line2D;
|
|||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "close" icon for windows (frames and dialogs).
|
* "close" icon for windows (frames and dialogs).
|
||||||
@@ -54,7 +55,7 @@ public class FlatWindowCloseIcon
|
|||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int ix2 = ix + iwh - 1;
|
int ix2 = ix + iwh - 1;
|
||||||
int iy2 = iy + iwh - 1;
|
int iy2 = iy + iwh - 1;
|
||||||
int thickness = (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "maximize" icon for windows (frames and dialogs).
|
* "maximize" icon for windows (frames and dialogs).
|
||||||
@@ -35,8 +36,11 @@ public class FlatWindowMaximizeIcon
|
|||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (10 * 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 thickness = (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
g.fill( SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix, iy, iwh, iwh, thickness, arc, arc, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ 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 com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "restore" icon for windows (frames and dialogs).
|
* "restore" icon for windows (frames and dialogs).
|
||||||
@@ -38,18 +39,33 @@ public class FlatWindowRestoreIcon
|
|||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (10 * 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 thickness = (int) scaleFactor;
|
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||||
|
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||||
|
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||||
|
|
||||||
int rwh = (int) (8 * scaleFactor);
|
int rwh = (int) (8 * scaleFactor);
|
||||||
int ro2 = iwh - rwh;
|
int ro2 = iwh - rwh;
|
||||||
|
|
||||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
// upper-right rectangle
|
||||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
Path2D r1 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix + ro2, iy, rwh, rwh, thickness, arc, arcOuter, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// lower-left rectangle
|
||||||
|
Path2D r2 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix, iy + ro2, rwh, rwh, thickness, arc, arc, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// paint upper-right rectangle
|
||||||
Area area = new Area( r1 );
|
Area area = new Area( r1 );
|
||||||
|
if( SystemInfo.isWindows_11_orLater ) {
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( ix, (float) (iy + scaleFactor), rwh, rwh ) ) );
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( (float) (ix + scaleFactor), iy + ro2, rwh, rwh ) ) );
|
||||||
|
} else
|
||||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||||
g.fill( area );
|
g.fill( area );
|
||||||
|
|
||||||
|
// paint lower-left rectangle
|
||||||
g.fill( r2 );
|
g.fill( r2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.resources;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
||||||
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
|
* Otherwise, the compiler outputs a warning because this package is opened in module-info.java.
|
||||||
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
* Also, when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class FlatArrowButton
|
|||||||
extends BasicArrowButton
|
extends BasicArrowButton
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||||
|
|
||||||
protected boolean chevron;
|
protected boolean chevron;
|
||||||
protected Color foreground;
|
protected Color foreground;
|
||||||
@@ -211,6 +211,6 @@ public class FlatArrowButton
|
|||||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||||
|
|
||||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, arrowWidth, xOffset, yOffset );
|
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, getArrowWidth(), getXOffset(), getYOffset() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class FlatButtonBorder
|
|||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||||
// In toolbars, use button margin only if explicitly set.
|
// In toolbars, use button margin only if explicitly set.
|
||||||
// Otherwise use toolbar margin specified in UI defaults.
|
// Otherwise, use toolbar margin specified in UI defaults.
|
||||||
Insets margin = (c instanceof AbstractButton)
|
Insets margin = (c instanceof AbstractButton)
|
||||||
? ((AbstractButton)c).getMargin()
|
? ((AbstractButton)c).getMargin()
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
@@ -38,15 +38,19 @@ import javax.swing.ButtonModel;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
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.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ButtonUI;
|
import javax.swing.plaf.ButtonUI;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
|
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;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
@@ -74,20 +78,27 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
||||||
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.focusedBackground Color optional
|
* @uiDefault Button.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.focusedForeground Color optional
|
||||||
* @uiDefault Button.hoverBackground Color optional
|
* @uiDefault Button.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.hoverForeground Color optional
|
||||||
* @uiDefault Button.pressedBackground Color optional
|
* @uiDefault Button.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.pressedForeground Color optional
|
||||||
* @uiDefault Button.selectedBackground Color
|
* @uiDefault Button.selectedBackground Color
|
||||||
* @uiDefault Button.selectedForeground Color
|
* @uiDefault Button.selectedForeground Color
|
||||||
* @uiDefault Button.disabledBackground Color optional
|
* @uiDefault Button.disabledBackground Color optional
|
||||||
* @uiDefault Button.disabledText Color
|
* @uiDefault Button.disabledText Color
|
||||||
* @uiDefault Button.disabledSelectedBackground Color
|
* @uiDefault Button.disabledSelectedBackground Color
|
||||||
|
* @uiDefault Button.disabledSelectedForeground Color optional
|
||||||
* @uiDefault Button.default.background Color
|
* @uiDefault Button.default.background Color
|
||||||
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
||||||
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.foreground Color
|
* @uiDefault Button.default.foreground Color
|
||||||
* @uiDefault Button.default.focusedBackground Color optional
|
* @uiDefault Button.default.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.default.focusedForeground Color optional
|
||||||
* @uiDefault Button.default.hoverBackground Color optional
|
* @uiDefault Button.default.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.default.hoverForeground Color optional
|
||||||
* @uiDefault Button.default.pressedBackground Color optional
|
* @uiDefault Button.default.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.default.pressedForeground Color optional
|
||||||
* @uiDefault Button.default.boldText boolean
|
* @uiDefault Button.default.boldText boolean
|
||||||
* @uiDefault Button.paintShadow boolean default is false
|
* @uiDefault Button.paintShadow boolean default is false
|
||||||
* @uiDefault Button.shadowWidth int default is 2
|
* @uiDefault Button.shadowWidth int default is 2
|
||||||
@@ -95,8 +106,13 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.default.shadowColor Color optional
|
* @uiDefault Button.default.shadowColor Color optional
|
||||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||||
* @uiDefault Button.toolbar.hoverBackground Color
|
* @uiDefault Button.toolbar.hoverBackground Color
|
||||||
|
* @uiDefault Button.toolbar.hoverForeground Color optional
|
||||||
* @uiDefault Button.toolbar.pressedBackground Color
|
* @uiDefault Button.toolbar.pressedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.pressedForeground Color optional
|
||||||
* @uiDefault Button.toolbar.selectedBackground Color
|
* @uiDefault Button.toolbar.selectedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.selectedForeground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedBackground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
@@ -113,20 +129,27 @@ public class FlatButtonUI
|
|||||||
protected Color startBackground;
|
protected Color startBackground;
|
||||||
protected Color endBackground;
|
protected Color endBackground;
|
||||||
@Styleable protected Color focusedBackground;
|
@Styleable protected Color focusedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color focusedForeground;
|
||||||
@Styleable protected Color hoverBackground;
|
@Styleable protected Color hoverBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color hoverForeground;
|
||||||
@Styleable protected Color pressedBackground;
|
@Styleable protected Color pressedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color pressedForeground;
|
||||||
@Styleable protected Color selectedBackground;
|
@Styleable protected Color selectedBackground;
|
||||||
@Styleable protected Color selectedForeground;
|
@Styleable protected Color selectedForeground;
|
||||||
@Styleable protected Color disabledBackground;
|
@Styleable protected Color disabledBackground;
|
||||||
@Styleable protected Color disabledText;
|
@Styleable protected Color disabledText;
|
||||||
@Styleable protected Color disabledSelectedBackground;
|
@Styleable protected Color disabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color disabledSelectedForeground;
|
||||||
|
|
||||||
@Styleable(dot=true) protected Color defaultBackground;
|
@Styleable(dot=true) protected Color defaultBackground;
|
||||||
protected Color defaultEndBackground;
|
protected Color defaultEndBackground;
|
||||||
@Styleable(dot=true) protected Color defaultForeground;
|
@Styleable(dot=true) protected Color defaultForeground;
|
||||||
@Styleable(dot=true) protected Color defaultFocusedBackground;
|
@Styleable(dot=true) protected Color defaultFocusedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultFocusedForeground;
|
||||||
@Styleable(dot=true) protected Color defaultHoverBackground;
|
@Styleable(dot=true) protected Color defaultHoverBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultHoverForeground;
|
||||||
@Styleable(dot=true) protected Color defaultPressedBackground;
|
@Styleable(dot=true) protected Color defaultPressedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultPressedForeground;
|
||||||
@Styleable(dot=true) protected boolean defaultBoldText;
|
@Styleable(dot=true) protected boolean defaultBoldText;
|
||||||
|
|
||||||
@Styleable protected boolean paintShadow;
|
@Styleable protected boolean paintShadow;
|
||||||
@@ -135,8 +158,13 @@ public class FlatButtonUI
|
|||||||
@Styleable(dot=true) protected Color defaultShadowColor;
|
@Styleable(dot=true) protected Color defaultShadowColor;
|
||||||
|
|
||||||
@Styleable(dot=true) protected Color toolbarHoverBackground;
|
@Styleable(dot=true) protected Color toolbarHoverBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarHoverForeground;
|
||||||
@Styleable(dot=true) protected Color toolbarPressedBackground;
|
@Styleable(dot=true) protected Color toolbarPressedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarPressedForeground;
|
||||||
@Styleable(dot=true) protected Color toolbarSelectedBackground;
|
@Styleable(dot=true) protected Color toolbarSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarSelectedForeground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedForeground;
|
||||||
|
|
||||||
// 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 String buttonType;
|
/** @since 2 */ @Styleable protected String buttonType;
|
||||||
@@ -186,20 +214,27 @@ public class FlatButtonUI
|
|||||||
startBackground = UIManager.getColor( prefix + "startBackground" );
|
startBackground = UIManager.getColor( prefix + "startBackground" );
|
||||||
endBackground = UIManager.getColor( prefix + "endBackground" );
|
endBackground = UIManager.getColor( prefix + "endBackground" );
|
||||||
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
||||||
|
focusedForeground = UIManager.getColor( prefix + "focusedForeground" );
|
||||||
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
||||||
|
hoverForeground = UIManager.getColor( prefix + "hoverForeground" );
|
||||||
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
||||||
|
pressedForeground = UIManager.getColor( prefix + "pressedForeground" );
|
||||||
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
||||||
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
||||||
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
||||||
disabledText = UIManager.getColor( prefix + "disabledText" );
|
disabledText = UIManager.getColor( prefix + "disabledText" );
|
||||||
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
||||||
|
disabledSelectedForeground = UIManager.getColor( prefix + "disabledSelectedForeground" );
|
||||||
|
|
||||||
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
||||||
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
||||||
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
||||||
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
||||||
|
defaultFocusedForeground = UIManager.getColor( "Button.default.focusedForeground" );
|
||||||
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
||||||
|
defaultHoverForeground = UIManager.getColor( "Button.default.hoverForeground" );
|
||||||
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
||||||
|
defaultPressedForeground = UIManager.getColor( "Button.default.pressedForeground" );
|
||||||
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
||||||
|
|
||||||
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
||||||
@@ -208,8 +243,13 @@ public class FlatButtonUI
|
|||||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||||
|
|
||||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||||
|
toolbarHoverForeground = UIManager.getColor( prefix + "toolbar.hoverForeground" );
|
||||||
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
||||||
|
toolbarPressedForeground = UIManager.getColor( prefix + "toolbar.pressedForeground" );
|
||||||
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
||||||
|
toolbarSelectedForeground = UIManager.getColor( prefix + "toolbar.selectedForeground" );
|
||||||
|
toolbarDisabledSelectedBackground = UIManager.getColor( prefix + "toolbar.disabledSelectedBackground" );
|
||||||
|
toolbarDisabledSelectedForeground = UIManager.getColor( prefix + "toolbar.disabledSelectedForeground" );
|
||||||
|
|
||||||
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
||||||
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
||||||
@@ -259,6 +299,10 @@ public class FlatButtonUI
|
|||||||
b.repaint();
|
b.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OUTLINE:
|
||||||
|
b.repaint();
|
||||||
|
break;
|
||||||
|
|
||||||
case STYLE:
|
case STYLE:
|
||||||
case STYLE_CLASS:
|
case STYLE_CLASS:
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||||
@@ -336,7 +380,7 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the button has an icon but no text,
|
* Returns true if the button has an icon but no text,
|
||||||
* or it it does not have an icon and the text is either "..." or one character.
|
* or it does not have an icon and the text is either "..." or one character.
|
||||||
*/
|
*/
|
||||||
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
||||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||||
@@ -420,11 +464,21 @@ public class FlatButtonUI
|
|||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
|
boolean def = isDefaultButton( c );
|
||||||
boolean isToolBarButton = isToolBarButton( c );
|
boolean isToolBarButton = isToolBarButton( c );
|
||||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
||||||
float arc = FlatUIUtils.getBorderArc( c );
|
float arc = FlatUIUtils.getBorderArc( c );
|
||||||
|
float textFieldArc = 0;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
// if toolbar button is in leading/trailing component of a text field,
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( isToolBarButton &&
|
||||||
|
FlatClientProperties.clientProperty( c, STYLE_CLASS, "", String.class ).contains( "inTextField" ) )
|
||||||
|
{
|
||||||
|
JTextField textField = (JTextField) SwingUtilities.getAncestorOfClass( JTextField.class, c );
|
||||||
|
if( textField != null )
|
||||||
|
textFieldArc = FlatUIUtils.getBorderArc( textField );
|
||||||
|
}
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
@@ -437,8 +491,15 @@ public class FlatButtonUI
|
|||||||
y += spacing.top;
|
y += spacing.top;
|
||||||
width -= spacing.left + spacing.right;
|
width -= spacing.left + spacing.right;
|
||||||
height -= spacing.top + spacing.bottom;
|
height -= spacing.top + spacing.bottom;
|
||||||
|
|
||||||
|
// reduce text field arc
|
||||||
|
textFieldArc -= spacing.top + spacing.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( arc < textFieldArc )
|
||||||
|
arc = textFieldArc;
|
||||||
|
|
||||||
// paint shadow
|
// paint shadow
|
||||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||||
if( paintShadow &&
|
if( paintShadow &&
|
||||||
@@ -470,6 +531,23 @@ public class FlatButtonUI
|
|||||||
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Graphics g, JComponent c, Rectangle iconRect ) {
|
||||||
|
// correct icon location when using bold font for default button
|
||||||
|
int xOffset = defaultBoldPlainWidthDiff( c ) / 2;
|
||||||
|
if( xOffset > 0 ) {
|
||||||
|
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
||||||
|
switch( ((AbstractButton)c).getHorizontalTextPosition() ) {
|
||||||
|
case SwingConstants.RIGHT: iconRect.x -= xOffset; break;
|
||||||
|
case SwingConstants.LEFT: iconRect.x += xOffset; break;
|
||||||
|
case SwingConstants.TRAILING: iconRect.x -= ltr ? xOffset : -xOffset; break;
|
||||||
|
case SwingConstants.LEADING: iconRect.x += ltr ? xOffset : -xOffset; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintIcon( g, c, iconRect );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
|
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
|
||||||
if( isHelpButton( b ) )
|
if( isHelpButton( b ) )
|
||||||
@@ -490,6 +568,8 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
|
||||||
|
if(foreground == null)
|
||||||
|
foreground=Color.red;
|
||||||
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;
|
||||||
|
|
||||||
@@ -503,11 +583,14 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
// selected state
|
// selected state
|
||||||
if( ((AbstractButton)c).isSelected() ) {
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
// in toolbar use same background colors for disabled and enabled because
|
// in toolbar, if toolbarDisabledSelectedBackground is null,
|
||||||
|
// use same background colors for disabled and enabled because
|
||||||
// we assume that toolbar icon is shown disabled
|
// we assume that toolbar icon is shown disabled
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||||
|
: disabledSelectedBackground,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||||
@@ -549,6 +632,9 @@ public class FlatButtonUI
|
|||||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||||
{
|
{
|
||||||
|
if( c == null )
|
||||||
|
return enabledColor;
|
||||||
|
|
||||||
if( !c.isEnabled() )
|
if( !c.isEnabled() )
|
||||||
return disabledColor;
|
return disabledColor;
|
||||||
|
|
||||||
@@ -569,18 +655,48 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( JComponent c ) {
|
protected Color getForeground( JComponent c ) {
|
||||||
if( !c.isEnabled() )
|
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||||
return disabledText;
|
|
||||||
|
|
||||||
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
|
// selected state
|
||||||
return selectedForeground;
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : c.getForeground())
|
||||||
|
: selectedForeground,
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
||||||
|
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
toolBarButton ? toolbarPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
// toolbar button
|
||||||
|
if( toolBarButton ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
c.getForeground(),
|
||||||
|
disabledText,
|
||||||
|
null,
|
||||||
|
toolbarHoverForeground,
|
||||||
|
toolbarPressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean def = isDefaultButton( c );
|
||||||
|
return buttonStateColor( c,
|
||||||
|
getForegroundBase( c, def ),
|
||||||
|
disabledText,
|
||||||
|
isCustomForeground( c.getForeground() ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
||||||
|
def ? defaultHoverForeground : hoverForeground,
|
||||||
|
def ? defaultPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected Color getForegroundBase( JComponent c, boolean def ) {
|
||||||
// use component foreground if explicitly set
|
// use component foreground if explicitly set
|
||||||
Color fg = c.getForeground();
|
Color fg = c.getForeground();
|
||||||
if( isCustomForeground( fg ) )
|
if( isCustomForeground( fg ) )
|
||||||
return fg;
|
return fg;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return def ? defaultForeground : fg;
|
return def ? defaultForeground : fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,6 +713,9 @@ public class FlatButtonUI
|
|||||||
if( prefSize == null )
|
if( prefSize == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// increase width when using bold font for default button
|
||||||
|
prefSize.width += defaultBoldPlainWidthDiff( c );
|
||||||
|
|
||||||
// make square or apply minimum width/height
|
// make square or apply minimum width/height
|
||||||
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
||||||
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
||||||
@@ -617,6 +736,23 @@ public class FlatButtonUI
|
|||||||
return prefSize;
|
return prefSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int defaultBoldPlainWidthDiff( JComponent c ) {
|
||||||
|
if( defaultBoldText && isDefaultButton( c ) && c.getFont() instanceof UIResource ) {
|
||||||
|
String text = ((AbstractButton)c).getText();
|
||||||
|
if( text == null || text.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Font font = c.getFont();
|
||||||
|
Font boldFont = font.deriveFont( Font.BOLD );
|
||||||
|
int boldWidth = c.getFontMetrics( boldFont ).stringWidth( text );
|
||||||
|
int plainWidth = c.getFontMetrics( font ).stringWidth( text );
|
||||||
|
if( boldWidth > plainWidth )
|
||||||
|
return boldWidth - plainWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasDefaultMargins( JComponent c ) {
|
private boolean hasDefaultMargins( JComponent c ) {
|
||||||
Insets margin = ((AbstractButton)c).getMargin();
|
Insets margin = ((AbstractButton)c).getMargin();
|
||||||
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class FlatCaret
|
|||||||
|
|
||||||
// if text component is focused, then caret and selection are visible,
|
// if text component is focused, then caret and selection are visible,
|
||||||
// but when switching theme, the component does not yet have
|
// but when switching theme, the component does not yet have
|
||||||
// an highlighter and the selection is not painted
|
// a highlighter and the selection is not painted
|
||||||
// --> make selection temporary invisible later, then the caret
|
// --> make selection temporary invisible later, then the caret
|
||||||
// adds selection highlights to the text component highlighter
|
// adds selection highlights to the text component highlighter
|
||||||
if( isSelectionVisible() ) {
|
if( isSelectionVisible() ) {
|
||||||
@@ -236,7 +236,7 @@ public class FlatCaret
|
|||||||
if( selectAllOnFocusPolicy == null )
|
if( selectAllOnFocusPolicy == null )
|
||||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||||
|
|
||||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault ComboBox.padding Insets
|
* @uiDefault ComboBox.padding Insets
|
||||||
* @uiDefault ComboBox.squareButton boolean default is true
|
* @uiDefault ComboBox.squareButton boolean default is true
|
||||||
*
|
*
|
||||||
|
* <!-- BasicComboPopup -->
|
||||||
|
*
|
||||||
|
* @uiDefault ComboBox.selectionBackground Color
|
||||||
|
* @uiDefault ComboBox.selectionForeground Color
|
||||||
|
*
|
||||||
* <!-- FlatComboBoxUI -->
|
* <!-- FlatComboBoxUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault ComboBox.minimumWidth int
|
* @uiDefault ComboBox.minimumWidth int
|
||||||
@@ -354,6 +359,7 @@ public class FlatComboBoxUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case COMPONENT_ROUND_RECT:
|
case COMPONENT_ROUND_RECT:
|
||||||
|
case OUTLINE:
|
||||||
comboBox.repaint();
|
comboBox.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -699,7 +705,7 @@ public class FlatComboBoxUI
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
return editorComponent != null && FlatUIUtils.isPermanentFocusOwner( editorComponent );
|
||||||
} else
|
} else
|
||||||
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,21 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@@ -34,12 +44,16 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.JToolBar;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.filechooser.FileSystemView;
|
||||||
import javax.swing.filechooser.FileView;
|
import javax.swing.filechooser.FileView;
|
||||||
import javax.swing.plaf.ComponentUI;
|
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.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;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -133,12 +147,21 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault FileChooser.listViewActionLabelText String
|
* @uiDefault FileChooser.listViewActionLabelText String
|
||||||
* @uiDefault FileChooser.detailsViewActionLabelText String
|
* @uiDefault FileChooser.detailsViewActionLabelText String
|
||||||
*
|
*
|
||||||
|
* <!-- FlatFileChooserUI -->
|
||||||
|
*
|
||||||
|
* @uiDefault FileChooser.shortcuts.buttonSize Dimension optional; default is 84,64
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconSize Dimension optional; default is 32,32
|
||||||
|
* @uiDefault FileChooser.shortcuts.filesFunction Function<File[], File[]>
|
||||||
|
* @uiDefault FileChooser.shortcuts.displayNameFunction Function<File, String>
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconFunction Function<File, Icon>
|
||||||
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatFileChooserUI
|
public class FlatFileChooserUI
|
||||||
extends MetalFileChooserUI
|
extends MetalFileChooserUI
|
||||||
{
|
{
|
||||||
private final FlatFileView fileView = new FlatFileView();
|
private final FlatFileView fileView = new FlatFileView();
|
||||||
|
private FlatShortcutsPanel shortcutsPanel;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatFileChooserUI( (JFileChooser) c );
|
return new FlatFileChooserUI( (JFileChooser) c );
|
||||||
@@ -153,6 +176,25 @@ public class FlatFileChooserUI
|
|||||||
super.installComponents( fc );
|
super.installComponents( fc );
|
||||||
|
|
||||||
patchUI( fc );
|
patchUI( fc );
|
||||||
|
|
||||||
|
if( !UIManager.getBoolean( "FileChooser.noPlacesBar" ) ) { // same as in Windows L&F
|
||||||
|
FlatShortcutsPanel panel = createShortcutsPanel( fc );
|
||||||
|
if( panel.getComponentCount() > 0 ) {
|
||||||
|
shortcutsPanel = panel;
|
||||||
|
fc.add( shortcutsPanel, BorderLayout.LINE_START );
|
||||||
|
fc.addPropertyChangeListener( shortcutsPanel );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uninstallComponents( JFileChooser fc ) {
|
||||||
|
super.uninstallComponents( fc );
|
||||||
|
|
||||||
|
if( shortcutsPanel != null ) {
|
||||||
|
fc.removePropertyChangeListener( shortcutsPanel );
|
||||||
|
shortcutsPanel = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void patchUI( JFileChooser fc ) {
|
private void patchUI( JFileChooser fc ) {
|
||||||
@@ -192,6 +234,25 @@ public class FlatFileChooserUI
|
|||||||
} catch( ArrayIndexOutOfBoundsException ex ) {
|
} catch( ArrayIndexOutOfBoundsException ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put north, center and south components into a new panel so that
|
||||||
|
// the shortcuts panel (at west) gets full height
|
||||||
|
LayoutManager layout = fc.getLayout();
|
||||||
|
if( layout instanceof BorderLayout ) {
|
||||||
|
BorderLayout borderLayout = (BorderLayout) layout;
|
||||||
|
borderLayout.setHgap( 8 );
|
||||||
|
|
||||||
|
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
||||||
|
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
||||||
|
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
||||||
|
if( north != null && center != null && south != null ) {
|
||||||
|
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
||||||
|
p.add( north, BorderLayout.NORTH );
|
||||||
|
p.add( center, BorderLayout.CENTER );
|
||||||
|
p.add( south, BorderLayout.SOUTH );
|
||||||
|
fc.add( p, BorderLayout.CENTER );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -250,9 +311,19 @@ public class FlatFileChooserUI
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
|
||||||
|
return new FlatShortcutsPanel( fc );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
return UIScale.scale( super.getPreferredSize( c ) );
|
Dimension prefSize = super.getPreferredSize( c );
|
||||||
|
Dimension minSize = getMinimumSize( c );
|
||||||
|
int shortcutsPanelWidth = (shortcutsPanel != null) ? shortcutsPanel.getPreferredSize().width : 0;
|
||||||
|
return new Dimension(
|
||||||
|
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
||||||
|
Math.max( prefSize.height, minSize.height ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -275,7 +346,10 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
private boolean doNotUseSystemIcons() {
|
private boolean doNotUseSystemIcons() {
|
||||||
// Java 17 32bit craches on Windows when using system icons
|
// Java 17 32bit craches on Windows when using system icons
|
||||||
return SystemInfo.isWindows && SystemInfo.isJava_17_orLater && !SystemInfo.isX86_64;
|
// fixed in Java 18+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||||
|
return SystemInfo.isWindows &&
|
||||||
|
SystemInfo.isX86 &&
|
||||||
|
(SystemInfo.isJava_17_orLater && !SystemInfo.isJava_18_orLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatFileView -------------------------------------------------
|
//---- class FlatFileView -------------------------------------------------
|
||||||
@@ -313,4 +387,234 @@ public class FlatFileChooserUI
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatShortcutsPanel -------------------------------------------
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
public static class FlatShortcutsPanel
|
||||||
|
extends JToolBar
|
||||||
|
implements PropertyChangeListener
|
||||||
|
{
|
||||||
|
private final JFileChooser fc;
|
||||||
|
|
||||||
|
private final Dimension buttonSize;
|
||||||
|
private final Dimension iconSize;
|
||||||
|
private final Function<File[], File[]> filesFunction;
|
||||||
|
private final Function<File, String> displayNameFunction;
|
||||||
|
private final Function<File, Icon> iconFunction;
|
||||||
|
|
||||||
|
protected final File[] files;
|
||||||
|
protected final JToggleButton[] buttons;
|
||||||
|
protected final ButtonGroup buttonGroup;
|
||||||
|
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
public FlatShortcutsPanel( JFileChooser fc ) {
|
||||||
|
super( JToolBar.VERTICAL );
|
||||||
|
this.fc = fc;
|
||||||
|
setFloatable( false );
|
||||||
|
|
||||||
|
buttonSize = UIScale.scale( getUIDimension( "FileChooser.shortcuts.buttonSize", 84, 64 ) );
|
||||||
|
iconSize = getUIDimension( "FileChooser.shortcuts.iconSize", 32, 32 );
|
||||||
|
|
||||||
|
filesFunction = (Function<File[], File[]>) UIManager.get( "FileChooser.shortcuts.filesFunction" );
|
||||||
|
displayNameFunction = (Function<File, String>) UIManager.get( "FileChooser.shortcuts.displayNameFunction" );
|
||||||
|
iconFunction = (Function<File, Icon>) UIManager.get( "FileChooser.shortcuts.iconFunction" );
|
||||||
|
|
||||||
|
FileSystemView fsv = fc.getFileSystemView();
|
||||||
|
File[] files = getChooserShortcutPanelFiles( fsv );
|
||||||
|
if( filesFunction != null )
|
||||||
|
files = filesFunction.apply( files );
|
||||||
|
this.files = files;
|
||||||
|
|
||||||
|
// create toolbar buttons
|
||||||
|
buttons = new JToggleButton[files.length];
|
||||||
|
buttonGroup = new ButtonGroup();
|
||||||
|
for( int i = 0; i < files.length; i++ ) {
|
||||||
|
// wrap drive path
|
||||||
|
if( fsv.isFileSystemRoot( files[i] ) )
|
||||||
|
files[i] = fsv.createFileObject( files[i].getAbsolutePath() );
|
||||||
|
|
||||||
|
File file = files[i];
|
||||||
|
String name = getDisplayName( fsv, file );
|
||||||
|
Icon icon = getIcon( fsv, file );
|
||||||
|
|
||||||
|
// remove path from name
|
||||||
|
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
||||||
|
if( lastSepIndex >= 0 && lastSepIndex < name.length() - 1 )
|
||||||
|
name = name.substring( lastSepIndex + 1 );
|
||||||
|
|
||||||
|
// scale icon (if necessary)
|
||||||
|
if( icon instanceof ImageIcon )
|
||||||
|
icon = new ScaledImageIcon( (ImageIcon) icon, iconSize.width, iconSize.height );
|
||||||
|
else if( icon != null )
|
||||||
|
icon = new ShortcutIcon( icon, iconSize.width, iconSize.height );
|
||||||
|
|
||||||
|
// create button
|
||||||
|
JToggleButton button = createButton( name, icon );
|
||||||
|
button.addActionListener( e -> {
|
||||||
|
fc.setCurrentDirectory( file );
|
||||||
|
} );
|
||||||
|
|
||||||
|
add( button );
|
||||||
|
buttonGroup.add( button );
|
||||||
|
buttons[i] = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimension getUIDimension( String key, int defaultWidth, int defaultHeight ) {
|
||||||
|
Dimension size = UIManager.getDimension( key );
|
||||||
|
if( size == null )
|
||||||
|
size = new Dimension( defaultWidth, defaultHeight );
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JToggleButton createButton( String name, Icon icon ) {
|
||||||
|
JToggleButton button = new JToggleButton( name, icon );
|
||||||
|
button.setVerticalTextPosition( SwingConstants.BOTTOM );
|
||||||
|
button.setHorizontalTextPosition( SwingConstants.CENTER );
|
||||||
|
button.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||||
|
button.setIconTextGap( 0 );
|
||||||
|
button.setPreferredSize( buttonSize );
|
||||||
|
button.setMaximumSize( buttonSize );
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File[] getChooserShortcutPanelFiles( FileSystemView fsv ) {
|
||||||
|
try {
|
||||||
|
if( SystemInfo.isJava_12_orLater ) {
|
||||||
|
Method m = fsv.getClass().getMethod( "getChooserShortcutPanelFiles" );
|
||||||
|
File[] files = (File[]) m.invoke( fsv );
|
||||||
|
|
||||||
|
// on macOS and Linux, files consists only of the user home directory
|
||||||
|
if( files.length == 1 && files[0].equals( new File( System.getProperty( "user.home" ) ) ) )
|
||||||
|
files = new File[0];
|
||||||
|
|
||||||
|
return files;
|
||||||
|
} else if( SystemInfo.isWindows ) {
|
||||||
|
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||||
|
Method m = cls.getMethod( "get", String.class );
|
||||||
|
return (File[]) m.invoke( null, "fileChooserShortcutPanelFolders" );
|
||||||
|
}
|
||||||
|
} catch( IllegalAccessException ex ) {
|
||||||
|
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
return new File[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDisplayName( FileSystemView fsv, File file ) {
|
||||||
|
if( displayNameFunction != null ) {
|
||||||
|
String name = displayNameFunction.apply( file );
|
||||||
|
if( name != null )
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fsv.getSystemDisplayName( file );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Icon getIcon( FileSystemView fsv, File file ) {
|
||||||
|
if( iconFunction != null ) {
|
||||||
|
Icon icon = iconFunction.apply( file );
|
||||||
|
if( icon != null )
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Java 17+ supports getting larger system icons
|
||||||
|
try {
|
||||||
|
if( SystemInfo.isJava_17_orLater ) {
|
||||||
|
Method m = fsv.getClass().getMethod( "getSystemIcon", File.class, int.class, int.class );
|
||||||
|
return (Icon) m.invoke( fsv, file, iconSize.width, iconSize.height );
|
||||||
|
} else if( iconSize.width > 16 || iconSize.height > 16 ) {
|
||||||
|
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||||
|
if( cls.isInstance( file ) ) {
|
||||||
|
Method m = file.getClass().getMethod( "getIcon", boolean.class );
|
||||||
|
m.setAccessible( true );
|
||||||
|
Image image = (Image) m.invoke( file, true );
|
||||||
|
if( image != null )
|
||||||
|
return new ImageIcon( image );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch( IllegalAccessException ex ) {
|
||||||
|
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// get system icon in default size 16x16
|
||||||
|
return fsv.getSystemIcon( file );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void directoryChanged( File file ) {
|
||||||
|
if( file != null ) {
|
||||||
|
String absolutePath = file.getAbsolutePath();
|
||||||
|
for( int i = 0; i < files.length; i++ ) {
|
||||||
|
// also compare path because otherwise selecting "Documents"
|
||||||
|
// in "Look in" combobox would not select "Documents" shortcut item
|
||||||
|
if( files[i].equals( file ) || files[i].getAbsolutePath().equals( absolutePath ) ) {
|
||||||
|
buttons[i].setSelected( true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonGroup.clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
|
||||||
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class ShortcutIcon -------------------------------------------------
|
||||||
|
|
||||||
|
private static class ShortcutIcon
|
||||||
|
implements Icon
|
||||||
|
{
|
||||||
|
private final Icon icon;
|
||||||
|
private final int iconWidth;
|
||||||
|
private final int iconHeight;
|
||||||
|
|
||||||
|
ShortcutIcon( Icon icon, int iconWidth, int iconHeight ) {
|
||||||
|
this.icon = icon;
|
||||||
|
this.iconWidth = iconWidth;
|
||||||
|
this.iconHeight = iconHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
try {
|
||||||
|
// set rendering hint for the case that the icon is a bitmap (not used for vector icons)
|
||||||
|
g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
|
||||||
|
|
||||||
|
double scale = (double) getIconWidth() / (double) icon.getIconWidth();
|
||||||
|
g2.translate( x, y );
|
||||||
|
g2.scale( scale, scale );
|
||||||
|
|
||||||
|
icon.paintIcon( c, g2, 0, 0 );
|
||||||
|
} finally {
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return UIScale.scale( iconWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return UIScale.scale( iconHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class FlatListCellBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because this borders are always shared for all lists,
|
* Because this border is always shared for all lists,
|
||||||
* get border specific style from FlatListUI.
|
* get border specific style from FlatListUI.
|
||||||
*/
|
*/
|
||||||
static <T> T getStyleFromListUI( Component c, Function<FlatListUI, T> f ) {
|
static <T> T getStyleFromListUI( Component c, Function<FlatListUI, T> f ) {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public class FlatListUI
|
|||||||
/**
|
/**
|
||||||
* Toggle selection colors from focused to inactive and vice versa.
|
* Toggle selection colors from focused to inactive and vice versa.
|
||||||
*
|
*
|
||||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||||
*
|
*
|
||||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||||
* already used in applications. Then either the inactive colors are not used,
|
* already used in applications. Then either the inactive colors are not used,
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public class FlatMenuBarUI
|
|||||||
// check whether:
|
// check whether:
|
||||||
// - TitlePane.unifiedBackground is true and
|
// - TitlePane.unifiedBackground is true and
|
||||||
// - menu bar is the "main" menu bar and
|
// - menu bar is the "main" menu bar and
|
||||||
// - window has custom decorations enabled
|
// - window root pane has custom decoration style
|
||||||
|
|
||||||
JRootPane rootPane;
|
JRootPane rootPane;
|
||||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||||
@@ -218,7 +218,7 @@ public class FlatMenuBarUI
|
|||||||
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||||
rootPane.getParent() instanceof Window &&
|
rootPane.getParent() instanceof Window &&
|
||||||
rootPane.getJMenuBar() == c &&
|
rootPane.getJMenuBar() == c &&
|
||||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() );
|
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class TakeFocus ----------------------------------------------------
|
//---- class TakeFocus ----------------------------------------------------
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import javax.swing.plaf.MenuBarUI;
|
|||||||
public class FlatMenuItemBorder
|
public class FlatMenuItemBorder
|
||||||
extends FlatMarginBorder
|
extends FlatMarginBorder
|
||||||
{
|
{
|
||||||
// only used if parent menubar is not a instance of FlatMenuBarUI
|
// only used if parent menubar is not an instance of FlatMenuBarUI
|
||||||
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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.io.File;
|
||||||
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.NativeLibrary;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to load FlatLaf native library (.dll, .so or .dylib),
|
||||||
|
* if available for current operating system and CPU architecture.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 2.3
|
||||||
|
*/
|
||||||
|
class FlatNativeLibrary
|
||||||
|
{
|
||||||
|
private static NativeLibrary nativeLibrary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads native library (if available) and returns whether loaded successfully.
|
||||||
|
* Returns {@code false} if no native library is available.
|
||||||
|
*/
|
||||||
|
static synchronized boolean isLoaded() {
|
||||||
|
initialize();
|
||||||
|
return (nativeLibrary != null) ? nativeLibrary.isLoaded() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initialize() {
|
||||||
|
if( nativeLibrary != null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
String libraryName;
|
||||||
|
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64) ) {
|
||||||
|
// Windows: requires Windows 10 (x86 or x86_64)
|
||||||
|
|
||||||
|
libraryName = "flatlaf-windows-x86";
|
||||||
|
if( SystemInfo.isX86_64 )
|
||||||
|
libraryName += "_64";
|
||||||
|
|
||||||
|
// load jawt native library
|
||||||
|
loadJAWT();
|
||||||
|
} else
|
||||||
|
return; // no native library available for current OS or CPU architecture
|
||||||
|
|
||||||
|
// load native library
|
||||||
|
nativeLibrary = createNativeLibrary( libraryName );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NativeLibrary createNativeLibrary( String libraryName ) {
|
||||||
|
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
|
||||||
|
if( libraryPath != null ) {
|
||||||
|
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
|
||||||
|
if( libraryFile.exists() )
|
||||||
|
return new NativeLibrary( libraryFile, true );
|
||||||
|
else
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void loadJAWT() {
|
||||||
|
if( SystemInfo.isJava_9_orLater )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
try {
|
||||||
|
System.loadLibrary( "jawt" );
|
||||||
|
} catch( UnsatisfiedLinkError ex ) {
|
||||||
|
// log error only if native library jawt.dll not already loaded
|
||||||
|
String message = ex.getMessage();
|
||||||
|
if( message == null || !message.contains( "already loaded in another classloader" ) )
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ public class FlatNativeWindowBorder
|
|||||||
private static final boolean canUseJBRCustomDecorations =
|
private static final boolean canUseJBRCustomDecorations =
|
||||||
canUseWindowDecorations &&
|
canUseWindowDecorations &&
|
||||||
SystemInfo.isJetBrainsJVM_11_orLater &&
|
SystemInfo.isJetBrainsJVM_11_orLater &&
|
||||||
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true );
|
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, false );
|
||||||
|
|
||||||
private static Boolean supported;
|
private static Boolean supported;
|
||||||
private static Provider nativeProvider;
|
private static Provider nativeProvider;
|
||||||
@@ -313,6 +313,10 @@ public class FlatNativeWindowBorder
|
|||||||
|
|
||||||
//---- class WindowTopBorder -------------------------------------------
|
//---- class WindowTopBorder -------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Window top border used on Windows 10.
|
||||||
|
* No longer needed since Windows 11.
|
||||||
|
*/
|
||||||
static class WindowTopBorder
|
static class WindowTopBorder
|
||||||
extends JBRCustomDecorations.JBRWindowTopBorder
|
extends JBRCustomDecorations.JBRWindowTopBorder
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import javax.swing.plaf.UIResource;
|
|||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.plaf.basic.BasicOptionPaneUI;
|
import javax.swing.plaf.basic.BasicOptionPaneUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.util.SwingUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,7 +157,7 @@ public class FlatOptionPaneUI
|
|||||||
|
|
||||||
// set icon-message gap
|
// set icon-message gap
|
||||||
if( iconMessageGap > 0 ) {
|
if( iconMessageGap > 0 ) {
|
||||||
Component iconMessageSeparator = findByName( messageArea, "OptionPane.separator" );
|
Component iconMessageSeparator = SwingUtils.getComponentByName( messageArea, "OptionPane.separator" );
|
||||||
if( iconMessageSeparator != null )
|
if( iconMessageSeparator != null )
|
||||||
iconMessageSeparator.setPreferredSize( new Dimension( UIScale.scale( iconMessageGap ), 1 ) );
|
iconMessageSeparator.setPreferredSize( new Dimension( UIScale.scale( iconMessageGap ), 1 ) );
|
||||||
}
|
}
|
||||||
@@ -236,20 +237,6 @@ public class FlatOptionPaneUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component findByName( Container c, String name ) {
|
|
||||||
for( Component child : c.getComponents() ) {
|
|
||||||
if( name.equals( child.getName() ) )
|
|
||||||
return child;
|
|
||||||
|
|
||||||
if( child instanceof Container ) {
|
|
||||||
Component c2 = findByName( (Container) child, name );
|
|
||||||
if( c2 != null )
|
|
||||||
return c2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean getSizeButtonsToSameWidth() {
|
protected boolean getSizeButtonsToSameWidth() {
|
||||||
return sameSizeButtons;
|
return sameSizeButtons;
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicPanelUI;
|
import javax.swing.plaf.basic.BasicPanelUI;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.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;
|
||||||
@@ -43,13 +45,12 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatPanelUI
|
public class FlatPanelUI
|
||||||
extends BasicPanelUI
|
extends BasicPanelUI
|
||||||
implements StyleableUI
|
implements StyleableUI, PropertyChangeListener
|
||||||
{
|
{
|
||||||
// only used via styling (not in UI defaults)
|
// only used via styling (not in UI defaults)
|
||||||
/** @since 2 */ @Styleable protected int arc = -1;
|
/** @since 2 */ @Styleable protected int arc = -1;
|
||||||
|
|
||||||
private final boolean shared;
|
private final boolean shared;
|
||||||
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 ) {
|
||||||
@@ -67,9 +68,7 @@ public class FlatPanelUI
|
|||||||
public void installUI( JComponent c ) {
|
public void installUI( JComponent c ) {
|
||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
c.addPropertyChangeListener( this );
|
||||||
c, () -> stylePropertyChange( (JPanel) c ), null );
|
|
||||||
c.addPropertyChangeListener( propertyChangeListener );
|
|
||||||
|
|
||||||
installStyle( (JPanel) c );
|
installStyle( (JPanel) c );
|
||||||
}
|
}
|
||||||
@@ -78,13 +77,18 @@ public class FlatPanelUI
|
|||||||
public void uninstallUI( JComponent c ) {
|
public void uninstallUI( JComponent c ) {
|
||||||
super.uninstallUI( c );
|
super.uninstallUI( c );
|
||||||
|
|
||||||
c.removePropertyChangeListener( propertyChangeListener );
|
c.removePropertyChangeListener( this );
|
||||||
propertyChangeListener = null;
|
|
||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stylePropertyChange( JPanel c ) {
|
/** @since 2.0.1 */
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case FlatClientProperties.STYLE:
|
||||||
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
|
JPanel c = (JPanel) e.getSource();
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( c ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( c ) ) {
|
||||||
// unshare component UI if necessary
|
// unshare component UI if necessary
|
||||||
// updateUI() invokes installStyle() from installUI()
|
// updateUI() invokes installStyle() from installUI()
|
||||||
@@ -93,6 +97,8 @@ public class FlatPanelUI
|
|||||||
installStyle( c );
|
installStyle( c );
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
c.repaint();
|
c.repaint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import javax.swing.Action;
|
|||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JPasswordField;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -38,6 +39,7 @@ import javax.swing.text.Element;
|
|||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import javax.swing.text.PasswordView;
|
import javax.swing.text.PasswordView;
|
||||||
import javax.swing.text.View;
|
import javax.swing.text.View;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
|
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -83,6 +85,9 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
public class FlatPasswordFieldUI
|
public class FlatPasswordFieldUI
|
||||||
extends FlatTextFieldUI
|
extends FlatTextFieldUI
|
||||||
{
|
{
|
||||||
|
// used to preserve reveal button state when switching theme
|
||||||
|
private static final String KEY_REVEAL_SELECTED = "FlatLaf.internal.FlatPasswordFieldUI.revealSelected";
|
||||||
|
|
||||||
private Character echoChar;
|
private Character echoChar;
|
||||||
|
|
||||||
@Styleable protected boolean showCapsLock;
|
@Styleable protected boolean showCapsLock;
|
||||||
@@ -93,6 +98,7 @@ public class FlatPasswordFieldUI
|
|||||||
private KeyListener capsLockListener;
|
private KeyListener capsLockListener;
|
||||||
private boolean capsLockIconShared = true;
|
private boolean capsLockIconShared = true;
|
||||||
private JToggleButton revealButton;
|
private JToggleButton revealButton;
|
||||||
|
private boolean uninstallEchoChar;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatPasswordFieldUI();
|
return new FlatPasswordFieldUI();
|
||||||
@@ -269,36 +275,65 @@ public class FlatPasswordFieldUI
|
|||||||
if( !showCapsLock )
|
if( !showCapsLock )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JTextComponent c = getComponent();
|
return FlatUIUtils.isPermanentFocusOwner( getComponent() ) &&
|
||||||
return FlatUIUtils.isPermanentFocusOwner( c ) &&
|
|
||||||
Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK );
|
Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void installRevealButton() {
|
protected void installRevealButton() {
|
||||||
JTextComponent c = getComponent();
|
|
||||||
if( showRevealButton ) {
|
if( showRevealButton ) {
|
||||||
revealButton = createRevealButton();
|
revealButton = createRevealButton();
|
||||||
installLayout();
|
installLayout();
|
||||||
c.add( revealButton );
|
getComponent().add( revealButton );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected JToggleButton createRevealButton() {
|
protected JToggleButton createRevealButton() {
|
||||||
JToggleButton button = new JToggleButton( revealIcon );
|
JToggleButton button = new JToggleButton( revealIcon );
|
||||||
|
button.setName( "PasswordField.revealButton" );
|
||||||
prepareLeadingOrTrailingComponent( button );
|
prepareLeadingOrTrailingComponent( button );
|
||||||
|
button.putClientProperty( FlatClientProperties.STYLE_CLASS, "inTextField revealButton" );
|
||||||
|
if( FlatClientProperties.clientPropertyBoolean( getComponent(), KEY_REVEAL_SELECTED, false ) ) {
|
||||||
|
button.setSelected( true );
|
||||||
|
updateEchoChar( true );
|
||||||
|
}
|
||||||
button.addActionListener( e -> {
|
button.addActionListener( e -> {
|
||||||
LookAndFeel.installProperty( getComponent(), "echoChar", button.isSelected()
|
boolean selected = button.isSelected();
|
||||||
? '\0'
|
updateEchoChar( selected );
|
||||||
: (echoChar != null ? echoChar : '*'));
|
getComponent().putClientProperty( KEY_REVEAL_SELECTED, selected );
|
||||||
} );
|
} );
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateEchoChar( boolean selected ) {
|
||||||
|
char newEchoChar = selected
|
||||||
|
? 0
|
||||||
|
: (echoChar != null ? echoChar : '*');
|
||||||
|
|
||||||
|
JPasswordField c = (JPasswordField) getComponent();
|
||||||
|
LookAndFeel.installProperty( c, "echoChar", newEchoChar );
|
||||||
|
|
||||||
|
// check whether was able to set echo char via LookAndFeel.installProperty()
|
||||||
|
// if not, then echo char was explicitly changed via JPasswordField.setEchoChar()
|
||||||
|
char actualEchoChar = c.getEchoChar();
|
||||||
|
if( actualEchoChar != newEchoChar ) {
|
||||||
|
if( selected && actualEchoChar != 0 ) {
|
||||||
|
// use explicitly set echo char
|
||||||
|
echoChar = actualEchoChar;
|
||||||
|
uninstallEchoChar = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.setEchoChar( newEchoChar );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void uninstallRevealButton() {
|
protected void uninstallRevealButton() {
|
||||||
if( revealButton != null ) {
|
if( revealButton != null ) {
|
||||||
|
if( uninstallEchoChar && revealButton.isSelected() )
|
||||||
|
((JPasswordField)getComponent()).setEchoChar( echoChar );
|
||||||
|
|
||||||
getComponent().remove( revealButton );
|
getComponent().remove( revealButton );
|
||||||
revealButton = null;
|
revealButton = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.AWTEvent;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.GraphicsDevice;
|
import java.awt.GraphicsDevice;
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
@@ -33,6 +35,7 @@ import java.awt.Toolkit;
|
|||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -140,7 +143,7 @@ public class FlatPopupFactory
|
|||||||
* <p>
|
* <p>
|
||||||
* On a dual screen setup, where screens use different scale factors, it may happen
|
* On a dual screen setup, where screens use different scale factors, it may happen
|
||||||
* that the window location changes when showing a heavy weight popup window.
|
* that the window location changes when showing a heavy weight popup window.
|
||||||
* E.g. when opening an dialog on the secondary screen and making combobox popup visible.
|
* E.g. when opening a dialog on the secondary screen and making combobox popup visible.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8224608
|
* This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8224608
|
||||||
*/
|
*/
|
||||||
@@ -219,7 +222,7 @@ public class FlatPopupFactory
|
|||||||
* and corrects the y-location so that the tooltip is placed above the mouse location.
|
* and corrects the y-location so that the tooltip is placed above the mouse location.
|
||||||
*/
|
*/
|
||||||
private Point fixToolTipLocation( Component owner, Component contents, int x, int y ) {
|
private Point fixToolTipLocation( Component owner, Component contents, int x, int y ) {
|
||||||
if( !(contents instanceof JToolTip) || !wasInvokedFromToolTipManager() )
|
if( !(contents instanceof JToolTip) || !wasInvokedFromToolTipManager() || hasTipLocation( owner ) )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||||
@@ -264,6 +267,35 @@ public class FlatPopupFactory
|
|||||||
return StackUtils.wasInvokedFrom( ToolTipManager.class.getName(), "showTipWindow", 8 );
|
return StackUtils.wasInvokedFrom( ToolTipManager.class.getName(), "showTipWindow", 8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the owner component returns a tooltip location in
|
||||||
|
* JComponent.getToolTipLocation(MouseEvent).
|
||||||
|
*/
|
||||||
|
private boolean hasTipLocation( Component owner ) {
|
||||||
|
if( !(owner instanceof JComponent) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AWTEvent e = EventQueue.getCurrentEvent();
|
||||||
|
MouseEvent me;
|
||||||
|
if( e instanceof MouseEvent )
|
||||||
|
me = (MouseEvent) e;
|
||||||
|
else {
|
||||||
|
// no mouse event available because a timer is used to show the tooltip
|
||||||
|
// --> create mouse event from current mouse location
|
||||||
|
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||||
|
if( pointerInfo == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Point location = new Point( pointerInfo.getLocation());
|
||||||
|
SwingUtilities.convertPointFromScreen( location, owner );
|
||||||
|
me = new MouseEvent( owner, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(),
|
||||||
|
0, location.x, location.y, 0, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
return me.getSource() == owner &&
|
||||||
|
((JComponent)owner).getToolTipLocation( me ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class NonFlashingPopup ---------------------------------------------
|
//---- class NonFlashingPopup ---------------------------------------------
|
||||||
|
|
||||||
private class NonFlashingPopup
|
private class NonFlashingPopup
|
||||||
|
|||||||
@@ -16,18 +16,58 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.GraphicsConfiguration;
|
||||||
|
import java.awt.GraphicsDevice;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.Insets;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
|
import java.awt.event.MouseWheelEvent;
|
||||||
|
import java.awt.event.MouseWheelListener;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JViewport;
|
||||||
|
import javax.swing.MenuElement;
|
||||||
|
import javax.swing.MenuSelectionManager;
|
||||||
|
import javax.swing.Popup;
|
||||||
|
import javax.swing.PopupFactory;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.MenuKeyEvent;
|
||||||
|
import javax.swing.event.MenuKeyListener;
|
||||||
|
import javax.swing.event.PopupMenuEvent;
|
||||||
|
import javax.swing.event.PopupMenuListener;
|
||||||
|
import javax.swing.plaf.ButtonUI;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
|
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.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;
|
||||||
|
|
||||||
@@ -41,12 +81,22 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* @uiDefault PopupMenu.foreground Color
|
* @uiDefault PopupMenu.foreground Color
|
||||||
* @uiDefault PopupMenu.border Border
|
* @uiDefault PopupMenu.border Border
|
||||||
*
|
*
|
||||||
|
* <!-- FlatPopupMenuUI -->
|
||||||
|
*
|
||||||
|
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||||
|
* @uiDefault PopupMenu.scrollArrowColor Color
|
||||||
|
* @uiDefault PopupMenu.hoverScrollArrowBackground Color optional
|
||||||
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatPopupMenuUI
|
public class FlatPopupMenuUI
|
||||||
extends BasicPopupMenuUI
|
extends BasicPopupMenuUI
|
||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
|
/** @since 2.1 */ @Styleable protected String arrowType;
|
||||||
|
/** @since 2.1 */ @Styleable protected Color scrollArrowColor;
|
||||||
|
/** @since 2.1 */ @Styleable protected Color hoverScrollArrowBackground;
|
||||||
|
|
||||||
private PropertyChangeListener propertyChangeListener;
|
private PropertyChangeListener propertyChangeListener;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
private AtomicBoolean borderShared;
|
private AtomicBoolean borderShared;
|
||||||
@@ -74,11 +124,23 @@ public class FlatPopupMenuUI
|
|||||||
public void installDefaults() {
|
public void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
|
arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
|
scrollArrowColor = UIManager.getColor( "PopupMenu.scrollArrowColor" );
|
||||||
|
hoverScrollArrowBackground = UIManager.getColor( "PopupMenu.hoverScrollArrowBackground" );
|
||||||
|
|
||||||
LayoutManager layout = popupMenu.getLayout();
|
LayoutManager layout = popupMenu.getLayout();
|
||||||
if( layout == null || layout instanceof UIResource )
|
if( layout == null || layout instanceof UIResource )
|
||||||
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallDefaults() {
|
||||||
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
scrollArrowColor = null;
|
||||||
|
hoverScrollArrowBackground = null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installListeners() {
|
protected void installListeners() {
|
||||||
super.installListeners();
|
super.installListeners();
|
||||||
@@ -122,6 +184,52 @@ public class FlatPopupMenuUI
|
|||||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() );
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Popup getPopup( JPopupMenu popup, int x, int y ) {
|
||||||
|
// do not add scroller to combobox popups or to popups that already have a scroll pane
|
||||||
|
if( popup instanceof BasicComboPopup ||
|
||||||
|
(popup.getComponentCount() > 0 && popup.getComponent( 0 ) instanceof JScrollPane) )
|
||||||
|
return super.getPopup( popup, x, y );
|
||||||
|
|
||||||
|
// do not add scroller if popup fits into screen
|
||||||
|
Dimension prefSize = popup.getPreferredSize();
|
||||||
|
int screenHeight = getScreenHeightAt( x, y );
|
||||||
|
if( prefSize.height <= screenHeight )
|
||||||
|
return super.getPopup( popup, x, y );
|
||||||
|
|
||||||
|
// create scroller
|
||||||
|
FlatPopupScroller scroller = new FlatPopupScroller( popup );
|
||||||
|
scroller.setPreferredSize( new Dimension( prefSize.width, screenHeight ) );
|
||||||
|
|
||||||
|
// create popup
|
||||||
|
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
||||||
|
return popupFactory.getPopup( popup.getInvoker(), scroller, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getScreenHeightAt( int x, int y ) {
|
||||||
|
// find GraphicsConfiguration at popup location (similar to JPopupMenu.getCurrentGraphicsConfiguration())
|
||||||
|
GraphicsConfiguration gc = null;
|
||||||
|
for( GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) {
|
||||||
|
if( device.getType() == GraphicsDevice.TYPE_RASTER_SCREEN ) {
|
||||||
|
GraphicsConfiguration dgc = device.getDefaultConfiguration();
|
||||||
|
if( dgc.getBounds().contains( x, y ) ) {
|
||||||
|
gc = dgc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( gc == null && popupMenu.getInvoker() != null )
|
||||||
|
gc = popupMenu.getInvoker().getGraphicsConfiguration();
|
||||||
|
|
||||||
|
// compute screen height
|
||||||
|
// (always subtract screen insets because there is no API to detect whether
|
||||||
|
// the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar())
|
||||||
|
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||||
|
Rectangle screenBounds = (gc != null) ? gc.getBounds() : new Rectangle( toolkit.getScreenSize() );
|
||||||
|
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
||||||
|
return screenBounds.height - screenInsets.top - screenInsets.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatMenuLayout -----------------------------------------------
|
//---- class FlatMenuLayout -----------------------------------------------
|
||||||
|
|
||||||
protected static class FlatMenuLayout
|
protected static class FlatMenuLayout
|
||||||
@@ -138,4 +246,206 @@ public class FlatPopupMenuUI
|
|||||||
return super.preferredLayoutSize( target );
|
return super.preferredLayoutSize( target );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatPopupScroller --------------------------------------------
|
||||||
|
|
||||||
|
private class FlatPopupScroller
|
||||||
|
extends JPanel
|
||||||
|
implements MouseWheelListener, PopupMenuListener, MenuKeyListener
|
||||||
|
{
|
||||||
|
private final JPopupMenu popup;
|
||||||
|
|
||||||
|
private final JScrollPane scrollPane;
|
||||||
|
private final JButton scrollUpButton;
|
||||||
|
private final JButton scrollDownButton;
|
||||||
|
private int unitIncrement;
|
||||||
|
|
||||||
|
FlatPopupScroller( JPopupMenu popup ) {
|
||||||
|
super( new BorderLayout() );
|
||||||
|
this.popup = popup;
|
||||||
|
|
||||||
|
// this panel is required to avoid that JPopupMenu.setLocation() will be invoked
|
||||||
|
// while scrolling, because this would call JPopupMenu.showPopup()
|
||||||
|
JPanel view = new JPanel( new BorderLayout() );
|
||||||
|
view.add( popup, BorderLayout.CENTER );
|
||||||
|
|
||||||
|
scrollPane = new JScrollPane( view, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
|
||||||
|
scrollPane.setBorder( null );
|
||||||
|
|
||||||
|
scrollUpButton = new ArrowButton( SwingConstants.NORTH );
|
||||||
|
scrollDownButton = new ArrowButton( SwingConstants.SOUTH );
|
||||||
|
|
||||||
|
add( scrollPane, BorderLayout.CENTER );
|
||||||
|
add( scrollUpButton, BorderLayout.NORTH );
|
||||||
|
add( scrollDownButton, BorderLayout.SOUTH );
|
||||||
|
|
||||||
|
setBackground( popup.getBackground() );
|
||||||
|
setBorder( popup.getBorder() );
|
||||||
|
popup.setBorder( null );
|
||||||
|
|
||||||
|
popup.addPopupMenuListener( this );
|
||||||
|
popup.addMouseWheelListener( this );
|
||||||
|
popup.addMenuKeyListener( this );
|
||||||
|
|
||||||
|
updateArrowButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void scroll( int unitsToScroll ) {
|
||||||
|
if( unitIncrement == 0 )
|
||||||
|
unitIncrement = new JMenuItem( "X" ).getPreferredSize().height;
|
||||||
|
|
||||||
|
JViewport viewport = scrollPane.getViewport();
|
||||||
|
Point viewPosition = viewport.getViewPosition();
|
||||||
|
int newY = viewPosition.y + (unitIncrement * unitsToScroll);
|
||||||
|
if( newY < 0 )
|
||||||
|
newY = 0;
|
||||||
|
else
|
||||||
|
newY = Math.min( newY, viewport.getViewSize().height - viewport.getExtentSize().height );
|
||||||
|
viewport.setViewPosition( new Point( viewPosition.x, newY ) );
|
||||||
|
|
||||||
|
updateArrowButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateArrowButtons() {
|
||||||
|
JViewport viewport = scrollPane.getViewport();
|
||||||
|
Point viewPosition = viewport.getViewPosition();
|
||||||
|
|
||||||
|
scrollUpButton.setVisible( viewPosition.y > 0 );
|
||||||
|
scrollDownButton.setVisible( viewPosition.y < viewport.getViewSize().height - viewport.getExtentSize().height );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface PopupMenuListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
|
||||||
|
// restore popup border
|
||||||
|
popup.setBorder( getBorder() );
|
||||||
|
|
||||||
|
popup.removePopupMenuListener( this );
|
||||||
|
popup.removeMouseWheelListener( this );
|
||||||
|
popup.removeMenuKeyListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {}
|
||||||
|
@Override public void popupMenuCanceled( PopupMenuEvent e ) {}
|
||||||
|
|
||||||
|
//---- interface MouseWheelListener ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll when user rotates mouse wheel.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void mouseWheelMoved( MouseWheelEvent e ) {
|
||||||
|
// convert mouse location before scrolling
|
||||||
|
Point mouseLocation = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), this );
|
||||||
|
|
||||||
|
// scroll
|
||||||
|
scroll( e.getUnitsToScroll() );
|
||||||
|
|
||||||
|
// select menu item at mouse location
|
||||||
|
Component c = SwingUtilities.getDeepestComponentAt( this, mouseLocation.x, mouseLocation.y );
|
||||||
|
if( c instanceof JMenuItem ) {
|
||||||
|
ButtonUI ui = ((JMenuItem)c).getUI();
|
||||||
|
if( ui instanceof BasicMenuItemUI )
|
||||||
|
MenuSelectionManager.defaultManager().setSelectedPath( ((BasicMenuItemUI)ui).getPath() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// this avoids that the popup is closed when running on Java 8
|
||||||
|
// https://bugs.openjdk.java.net/browse/JDK-8075063
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface MenuKeyListener ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll when user presses Up or Down keys.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void menuKeyPressed( MenuKeyEvent e ) {
|
||||||
|
// use invokeLater() because menu selection is not yet updated because
|
||||||
|
// this listener is invoked before another listener that updates the menu selection
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
if( !isDisplayable() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
|
if( path.length == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// scroll selected menu item to visible area
|
||||||
|
Component c = path[path.length - 1].getComponent();
|
||||||
|
JViewport viewport = scrollPane.getViewport();
|
||||||
|
Point pt = SwingUtilities.convertPoint( c, 0, 0, viewport );
|
||||||
|
viewport.scrollRectToVisible( new Rectangle( pt, c.getSize() ) );
|
||||||
|
|
||||||
|
// update arrow buttons
|
||||||
|
boolean upVisible = scrollUpButton.isVisible();
|
||||||
|
updateArrowButtons();
|
||||||
|
if( !upVisible && scrollUpButton.isVisible() ) {
|
||||||
|
// if "up" button becomes visible, make sure that bottom menu item stays visible
|
||||||
|
Point viewPosition = viewport.getViewPosition();
|
||||||
|
int newY = viewPosition.y + scrollUpButton.getPreferredSize().height;
|
||||||
|
viewport.setViewPosition( new Point( viewPosition.x, newY ) );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void menuKeyTyped( MenuKeyEvent e ) {}
|
||||||
|
@Override public void menuKeyReleased( MenuKeyEvent e ) {}
|
||||||
|
|
||||||
|
//---- class ArrowButton ----------------------------------------------
|
||||||
|
|
||||||
|
private class ArrowButton
|
||||||
|
extends FlatArrowButton
|
||||||
|
implements MouseListener, ActionListener
|
||||||
|
{
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
|
ArrowButton( int direction ) {
|
||||||
|
super( direction, arrowType, scrollArrowColor, null, null, hoverScrollArrowBackground, null, null );
|
||||||
|
|
||||||
|
addMouseListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint( Graphics g ) {
|
||||||
|
// always fill background to paint over border on HiDPI screens
|
||||||
|
g.setColor( popup.getBackground() );
|
||||||
|
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||||
|
|
||||||
|
super.paint( g );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface MouseListener ----
|
||||||
|
|
||||||
|
@Override public void mouseClicked( MouseEvent e ) {}
|
||||||
|
@Override public void mousePressed( MouseEvent e ) {}
|
||||||
|
@Override public void mouseReleased( MouseEvent e ) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEntered( MouseEvent e ) {
|
||||||
|
if( timer == null )
|
||||||
|
timer = new Timer( 50, this );
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited( MouseEvent e ) {
|
||||||
|
if( timer != null )
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface ActionListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed( ActionEvent e ) {
|
||||||
|
if( timer != null && !isDisplayable() ) {
|
||||||
|
timer.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll( direction == SwingConstants.NORTH ? -1 : 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ public class FlatRadioButtonUI
|
|||||||
return infos;
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Insets tempInsets = new Insets( 0, 0, 0, 0 );
|
private static final Insets tempInsets = new Insets( 0, 0, 0, 0 );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
@@ -212,7 +212,7 @@ public class FlatRadioButtonUI
|
|||||||
if( focusWidth > 0 ) {
|
if( focusWidth > 0 ) {
|
||||||
// Increase preferred width and height if insets were explicitly reduced (e.g. with
|
// Increase preferred width and height if insets were explicitly reduced (e.g. with
|
||||||
// an EmptyBorder) and icon has a focus width, which is not included in icon size.
|
// an EmptyBorder) and icon has a focus width, which is not included in icon size.
|
||||||
// Otherwise the component may be too small and outer focus border may be cut off.
|
// Otherwise, the component may be too small and outer focus border may be cut off.
|
||||||
Insets insets = c.getInsets( tempInsets );
|
Insets insets = c.getInsets( tempInsets );
|
||||||
size.width += Math.max( focusWidth - insets.left, 0 ) + Math.max( focusWidth - insets.right, 0 );
|
size.width += Math.max( focusWidth - insets.left, 0 ) + Math.max( focusWidth - insets.right, 0 );
|
||||||
size.height += Math.max( focusWidth - insets.top, 0 ) + Math.max( focusWidth - insets.bottom, 0 );
|
size.height += Math.max( focusWidth - insets.top, 0 ) + Math.max( focusWidth - insets.bottom, 0 );
|
||||||
|
|||||||
@@ -161,13 +161,26 @@ public class FlatRootPaneUI
|
|||||||
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallDefaults( JRootPane c ) {
|
||||||
|
super.uninstallDefaults( c );
|
||||||
|
|
||||||
|
// uninstall background, foreground and font because not all Lafs set them
|
||||||
|
if( c.isBackgroundSet() && c.getBackground() instanceof UIResource )
|
||||||
|
c.setBackground( null );
|
||||||
|
if( c.isForegroundSet() && c.getForeground() instanceof UIResource )
|
||||||
|
c.setForeground( null );
|
||||||
|
if( c.isFontSet() && c.getFont() instanceof UIResource )
|
||||||
|
c.setFont( null );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installListeners( JRootPane root ) {
|
protected void installListeners( JRootPane root ) {
|
||||||
super.installListeners( root );
|
super.installListeners( root );
|
||||||
|
|
||||||
if( SystemInfo.isJava_9_orLater ) {
|
if( SystemInfo.isJava_9_orLater ) {
|
||||||
// On HiDPI screens, where scaling is used, there may be white lines at the
|
// On HiDPI screens, where scaling is used, there may be white lines on the
|
||||||
// bottom and at the right side of the window when it is initially shown.
|
// bottom and on the right side of the window when it is initially shown.
|
||||||
// This is very disturbing in dark themes, but hard to notice in light themes.
|
// This is very disturbing in dark themes, but hard to notice in light themes.
|
||||||
// Seems to be a rounding issue when Swing adds dirty region of window
|
// Seems to be a rounding issue when Swing adds dirty region of window
|
||||||
// using RepaintManager.nativeAddDirtyRegion().
|
// using RepaintManager.nativeAddDirtyRegion().
|
||||||
@@ -497,7 +510,7 @@ public class FlatRootPaneUI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Container parent = c.getParent();
|
Container parent = c.getParent();
|
||||||
boolean active = parent instanceof Window ? ((Window)parent).isActive() : false;
|
boolean active = parent instanceof Window && ((Window)parent).isActive();
|
||||||
|
|
||||||
g.setColor( FlatUIUtils.deriveColor( active ? activeBorderColor : inactiveBorderColor, baseBorderColor ) );
|
g.setColor( FlatUIUtils.deriveColor( active ? activeBorderColor : inactiveBorderColor, baseBorderColor ) );
|
||||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
||||||
@@ -509,9 +522,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
|
return parent instanceof Frame && (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||||
? (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
|
|
||||||
: false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*
|
*
|
||||||
* <!-- FlatScrollBarUI -->
|
* <!-- FlatScrollBarUI -->
|
||||||
*
|
*
|
||||||
|
* @uiDefault ScrollBar.minimumButtonSize Dimension
|
||||||
* @uiDefault ScrollBar.trackInsets Insets
|
* @uiDefault ScrollBar.trackInsets Insets
|
||||||
* @uiDefault ScrollBar.thumbInsets Insets
|
* @uiDefault ScrollBar.thumbInsets Insets
|
||||||
* @uiDefault ScrollBar.trackArc int
|
* @uiDefault ScrollBar.trackArc int
|
||||||
@@ -83,6 +84,7 @@ public class FlatScrollBarUI
|
|||||||
// overrides BasicScrollBarUI.supportsAbsolutePositioning (which is private)
|
// overrides BasicScrollBarUI.supportsAbsolutePositioning (which is private)
|
||||||
@Styleable protected boolean allowsAbsolutePositioning;
|
@Styleable protected boolean allowsAbsolutePositioning;
|
||||||
|
|
||||||
|
/** @since 2.1 */ @Styleable protected Dimension minimumButtonSize;
|
||||||
@Styleable protected Insets trackInsets;
|
@Styleable protected Insets trackInsets;
|
||||||
@Styleable protected Insets thumbInsets;
|
@Styleable protected Insets thumbInsets;
|
||||||
@Styleable protected int trackArc;
|
@Styleable protected int trackArc;
|
||||||
@@ -142,6 +144,7 @@ public class FlatScrollBarUI
|
|||||||
|
|
||||||
allowsAbsolutePositioning = super.getSupportsAbsolutePositioning();
|
allowsAbsolutePositioning = super.getSupportsAbsolutePositioning();
|
||||||
|
|
||||||
|
minimumButtonSize = UIManager.getDimension( "ScrollBar.minimumButtonSize" );
|
||||||
trackInsets = UIManager.getInsets( "ScrollBar.trackInsets" );
|
trackInsets = UIManager.getInsets( "ScrollBar.trackInsets" );
|
||||||
thumbInsets = UIManager.getInsets( "ScrollBar.thumbInsets" );
|
thumbInsets = UIManager.getInsets( "ScrollBar.thumbInsets" );
|
||||||
trackArc = UIManager.getInt( "ScrollBar.trackArc" );
|
trackArc = UIManager.getInt( "ScrollBar.trackArc" );
|
||||||
@@ -171,6 +174,7 @@ public class FlatScrollBarUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
minimumButtonSize = null;
|
||||||
trackInsets = null;
|
trackInsets = null;
|
||||||
thumbInsets = null;
|
thumbInsets = null;
|
||||||
hoverTrackColor = null;
|
hoverTrackColor = null;
|
||||||
@@ -451,7 +455,6 @@ public class FlatScrollBarUI
|
|||||||
super( direction, type, foreground, disabledForeground,
|
super( direction, type, foreground, disabledForeground,
|
||||||
hoverForeground, hoverBackground, pressedForeground, pressedBackground );
|
hoverForeground, hoverBackground, pressedForeground, pressedBackground );
|
||||||
|
|
||||||
setArrowWidth( FlatArrowButton.DEFAULT_ARROW_WIDTH - 2 );
|
|
||||||
setFocusable( false );
|
setFocusable( false );
|
||||||
setRequestFocusEnabled( false );
|
setRequestFocusEnabled( false );
|
||||||
}
|
}
|
||||||
@@ -461,6 +464,18 @@ public class FlatScrollBarUI
|
|||||||
null, hoverButtonBackground, null, pressedButtonBackground );
|
null, hoverButtonBackground, null, pressedButtonBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getArrowWidth() {
|
||||||
|
// scale arrow size depending on scroll bar width
|
||||||
|
// (6 is default arrow width; 10 is base scroll bar width)
|
||||||
|
int arrowWidth = Math.round( 6 * (scrollBarWidth / 10f) );
|
||||||
|
|
||||||
|
// compute arrow size that leaves equal space on both sides (arrow is centered)
|
||||||
|
arrowWidth = scrollBarWidth - (((scrollBarWidth - arrowWidth) / 2) * 2);
|
||||||
|
|
||||||
|
return arrowWidth;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Color deriveBackground( Color background ) {
|
protected Color deriveBackground( Color background ) {
|
||||||
return FlatUIUtils.deriveColor( background, scrollbar.getBackground() );
|
return FlatUIUtils.deriveColor( background, scrollbar.getBackground() );
|
||||||
@@ -469,8 +484,9 @@ public class FlatScrollBarUI
|
|||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize() {
|
public Dimension getPreferredSize() {
|
||||||
if( isShowButtons() ) {
|
if( isShowButtons() ) {
|
||||||
int w = UIScale.scale( scrollBarWidth );
|
int w = UIScale.scale( Math.max( scrollBarWidth, (minimumButtonSize != null) ? minimumButtonSize.width : 0 ) );
|
||||||
return new Dimension( w, w );
|
int h = UIScale.scale( Math.max( scrollBarWidth, (minimumButtonSize != null) ? minimumButtonSize.height : 0 ) );
|
||||||
|
return new Dimension( w, h );
|
||||||
} else
|
} else
|
||||||
return new Dimension();
|
return new Dimension();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,6 +291,10 @@ public class FlatScrollPaneUI
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.OUTLINE:
|
||||||
|
scrollpane.repaint();
|
||||||
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.STYLE:
|
case FlatClientProperties.STYLE:
|
||||||
case FlatClientProperties.STYLE_CLASS:
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
installStyle();
|
installStyle();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -28,6 +29,7 @@ import javax.swing.JSeparator;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicSeparatorUI;
|
import javax.swing.plaf.basic.BasicSeparatorUI;
|
||||||
|
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;
|
||||||
@@ -50,7 +52,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
*/
|
*/
|
||||||
public class FlatSeparatorUI
|
public class FlatSeparatorUI
|
||||||
extends BasicSeparatorUI
|
extends BasicSeparatorUI
|
||||||
implements StyleableUI
|
implements StyleableUI, PropertyChangeListener
|
||||||
{
|
{
|
||||||
@Styleable protected int height;
|
@Styleable protected int height;
|
||||||
@Styleable protected int stripeWidth;
|
@Styleable protected int stripeWidth;
|
||||||
@@ -58,7 +60,6 @@ public class FlatSeparatorUI
|
|||||||
|
|
||||||
private final boolean shared;
|
private final boolean shared;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
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 ) {
|
||||||
@@ -109,20 +110,23 @@ public class FlatSeparatorUI
|
|||||||
protected void installListeners( JSeparator s ) {
|
protected void installListeners( JSeparator s ) {
|
||||||
super.installListeners( s );
|
super.installListeners( s );
|
||||||
|
|
||||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
s.addPropertyChangeListener( this );
|
||||||
s, () -> stylePropertyChange( s ), null );
|
|
||||||
s.addPropertyChangeListener( propertyChangeListener );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void uninstallListeners( JSeparator s ) {
|
protected void uninstallListeners( JSeparator s ) {
|
||||||
super.uninstallListeners( s );
|
super.uninstallListeners( s );
|
||||||
|
|
||||||
s.removePropertyChangeListener( propertyChangeListener );
|
s.removePropertyChangeListener( this );
|
||||||
propertyChangeListener = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stylePropertyChange( JSeparator s ) {
|
/** @since 2.0.1 */
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case FlatClientProperties.STYLE:
|
||||||
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
|
JSeparator s = (JSeparator) e.getSource();
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||||
// unshare component UI if necessary
|
// unshare component UI if necessary
|
||||||
// updateUI() invokes installStyle() from installUI()
|
// updateUI() invokes installStyle() from installUI()
|
||||||
@@ -131,6 +135,8 @@ public class FlatSeparatorUI
|
|||||||
installStyle( s );
|
installStyle( s );
|
||||||
s.revalidate();
|
s.revalidate();
|
||||||
s.repaint();
|
s.repaint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ public class FlatSliderUI
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// use default font (instead of slider font) because the slider font size
|
// use default font (instead of slider font) because the slider font size
|
||||||
// may be different to label font size, but we want align the track/thumb with labels
|
// may be different to label font size, but we want to align the track/thumb with labels
|
||||||
Font font = UIManager.getFont( "defaultFont" );
|
Font font = UIManager.getFont( "defaultFont" );
|
||||||
if( font == null )
|
if( font == null )
|
||||||
font = slider.getFont();
|
font = slider.getFont();
|
||||||
|
|||||||
@@ -293,9 +293,7 @@ public class FlatSpinnerUI
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
JTextField textField = getEditorTextField( spinner.getEditor() );
|
JTextField textField = getEditorTextField( spinner.getEditor() );
|
||||||
return (textField != null)
|
return textField != null && FlatUIUtils.isPermanentFocusOwner( textField );
|
||||||
? FlatUIUtils.isPermanentFocusOwner( textField )
|
|
||||||
: false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackground( boolean enabled ) {
|
protected Color getBackground( boolean enabled ) {
|
||||||
@@ -447,7 +445,7 @@ public class FlatSpinnerUI
|
|||||||
Insets padding = scale( FlatSpinnerUI.this.padding );
|
Insets padding = scale( FlatSpinnerUI.this.padding );
|
||||||
Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 );
|
Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 );
|
||||||
|
|
||||||
// the arrows width is the same as the inner height so that the arrows area is square
|
// the arrow buttons width is the same as the inner height so that the arrow buttons area is square
|
||||||
int minimumWidth = FlatUIUtils.minimumWidth( spinner, FlatSpinnerUI.this.minimumWidth );
|
int minimumWidth = FlatUIUtils.minimumWidth( spinner, FlatSpinnerUI.this.minimumWidth );
|
||||||
int innerHeight = editorSize.height + padding.top + padding.bottom;
|
int innerHeight = editorSize.height + padding.top + padding.bottom;
|
||||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( spinner );
|
float focusWidth = FlatUIUtils.getBorderFocusWidth( spinner );
|
||||||
@@ -538,6 +536,7 @@ public class FlatSpinnerUI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
||||||
|
case FlatClientProperties.OUTLINE:
|
||||||
spinner.repaint();
|
spinner.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||||
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
||||||
|
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.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
@@ -52,6 +53,13 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault SplitPaneDivider.border Border
|
* @uiDefault SplitPaneDivider.border Border
|
||||||
* @uiDefault SplitPaneDivider.draggingColor Color only used if continuousLayout is false
|
* @uiDefault SplitPaneDivider.draggingColor Color only used if continuousLayout is false
|
||||||
*
|
*
|
||||||
|
* <!-- BasicSplitPaneDivider -->
|
||||||
|
*
|
||||||
|
* @uiDefault SplitPane.oneTouchButtonSize int
|
||||||
|
* @uiDefault SplitPane.oneTouchButtonOffset int
|
||||||
|
* @uiDefault SplitPane.centerOneTouchButtons boolean
|
||||||
|
* @uiDefault SplitPane.supportsOneTouchButtons boolean optional; default is true
|
||||||
|
*
|
||||||
* <!-- JSplitPane -->
|
* <!-- JSplitPane -->
|
||||||
*
|
*
|
||||||
* @uiDefault SplitPane.continuousLayout boolean
|
* @uiDefault SplitPane.continuousLayout boolean
|
||||||
@@ -235,7 +243,7 @@ public class FlatSplitPaneUI
|
|||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
case JSplitPane.DIVIDER_LOCATION_PROPERTY:
|
case JSplitPane.DIVIDER_LOCATION_PROPERTY:
|
||||||
// necessary to show/hide one-touch buttons on expand/collapse
|
// necessary to show/hide one-touch buttons on expand/collapse
|
||||||
revalidate();
|
doLayout();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +353,7 @@ public class FlatSplitPaneUI
|
|||||||
if( leftButton == null || rightButton == null || !splitPane.isOneTouchExpandable() )
|
if( leftButton == null || rightButton == null || !splitPane.isOneTouchExpandable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// increase side of buttons, which makes them easier to hit by the user
|
// increase size of buttons, which makes them easier to hit by the user
|
||||||
// and avoids cut arrows at small divider sizes
|
// and avoids cut arrows at small divider sizes
|
||||||
int extraSize = UIScale.scale( 4 );
|
int extraSize = UIScale.scale( 4 );
|
||||||
if( orientation == JSplitPane.VERTICAL_SPLIT ) {
|
if( orientation == JSplitPane.VERTICAL_SPLIT ) {
|
||||||
@@ -360,10 +368,19 @@ public class FlatSplitPaneUI
|
|||||||
|
|
||||||
// hide buttons if not applicable
|
// hide buttons if not applicable
|
||||||
boolean leftCollapsed = isLeftCollapsed();
|
boolean leftCollapsed = isLeftCollapsed();
|
||||||
if( leftCollapsed )
|
boolean rightCollapsed = isRightCollapsed();
|
||||||
rightButton.setLocation( leftButton.getLocation() );
|
if( leftCollapsed || rightCollapsed ) {
|
||||||
leftButton.setVisible( !leftCollapsed );
|
leftButton.setVisible( !leftCollapsed );
|
||||||
rightButton.setVisible( !isRightCollapsed() );
|
rightButton.setVisible( !rightCollapsed );
|
||||||
|
} else {
|
||||||
|
Object expandableSide = splitPane.getClientProperty( FlatClientProperties.SPLIT_PANE_EXPANDABLE_SIDE );
|
||||||
|
leftButton.setVisible( expandableSide == null || !FlatClientProperties.SPLIT_PANE_EXPANDABLE_SIDE_LEFT.equals( expandableSide ) );
|
||||||
|
rightButton.setVisible( expandableSide == null || !FlatClientProperties.SPLIT_PANE_EXPANDABLE_SIDE_RIGHT.equals( expandableSide ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// move right button if left button is hidden
|
||||||
|
if( !leftButton.isVisible() )
|
||||||
|
rightButton.setLocation( leftButton.getLocation() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ public class FlatStylingSupport
|
|||||||
* @param key the name of the field
|
* @param key the name of the field
|
||||||
* @param value the new value
|
* @param value the new value
|
||||||
* @return the old value of the field
|
* @return the old value of the field
|
||||||
* @throws UnknownStyleException if object does not have a annotated field with given name
|
* @throws UnknownStyleException if object does not have an annotated field with given name
|
||||||
* @throws IllegalArgumentException if value type does not fit to expected type
|
* @throws IllegalArgumentException if value type does not fit to expected type
|
||||||
*/
|
*/
|
||||||
public static Object applyToAnnotatedObject( Object obj, String key, Object value )
|
public static Object applyToAnnotatedObject( Object obj, String key, Object value )
|
||||||
@@ -517,7 +517,7 @@ public class FlatStylingSupport
|
|||||||
* @param key the name of the field
|
* @param key the name of the field
|
||||||
* @param value the new value
|
* @param value the new value
|
||||||
* @return the old value of the field
|
* @return the old value of the field
|
||||||
* @throws UnknownStyleException if object does not have a annotated field with given name
|
* @throws UnknownStyleException if object does not have an annotated field with given name
|
||||||
* @throws IllegalArgumentException if value type does not fit to expected type
|
* @throws IllegalArgumentException if value type does not fit to expected type
|
||||||
*/
|
*/
|
||||||
public static Object applyToAnnotatedObjectOrComponent( Object obj, Object comp, String key, Object value )
|
public static Object applyToAnnotatedObjectOrComponent( Object obj, Object comp, String key, Object value )
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import javax.accessibility.Accessible;
|
import javax.accessibility.Accessible;
|
||||||
import javax.accessibility.AccessibleContext;
|
import javax.accessibility.AccessibleContext;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
@@ -82,10 +83,12 @@ import javax.swing.event.ChangeListener;
|
|||||||
import javax.swing.event.PopupMenuEvent;
|
import javax.swing.event.PopupMenuEvent;
|
||||||
import javax.swing.event.PopupMenuListener;
|
import javax.swing.event.PopupMenuListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.TabbedPaneUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import javax.swing.text.View;
|
import javax.swing.text.View;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon;
|
import com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
@@ -127,6 +130,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TabbedPane.selectedBackground Color optional
|
* @uiDefault TabbedPane.selectedBackground Color optional
|
||||||
* @uiDefault TabbedPane.selectedForeground Color
|
* @uiDefault TabbedPane.selectedForeground Color
|
||||||
* @uiDefault TabbedPane.underlineColor Color
|
* @uiDefault TabbedPane.underlineColor Color
|
||||||
|
* @uiDefault TabbedPane.inactiveUnderlineColor Color
|
||||||
* @uiDefault TabbedPane.disabledUnderlineColor Color
|
* @uiDefault TabbedPane.disabledUnderlineColor Color
|
||||||
* @uiDefault TabbedPane.hoverColor Color
|
* @uiDefault TabbedPane.hoverColor Color
|
||||||
* @uiDefault TabbedPane.focusColor Color
|
* @uiDefault TabbedPane.focusColor Color
|
||||||
@@ -198,6 +202,7 @@ public class FlatTabbedPaneUI
|
|||||||
@Styleable protected Color selectedBackground;
|
@Styleable protected Color selectedBackground;
|
||||||
@Styleable protected Color selectedForeground;
|
@Styleable protected Color selectedForeground;
|
||||||
@Styleable protected Color underlineColor;
|
@Styleable protected Color underlineColor;
|
||||||
|
/** @since 2.2 */ @Styleable protected Color inactiveUnderlineColor;
|
||||||
@Styleable protected Color disabledUnderlineColor;
|
@Styleable protected Color disabledUnderlineColor;
|
||||||
@Styleable protected Color hoverColor;
|
@Styleable protected Color hoverColor;
|
||||||
@Styleable protected Color focusColor;
|
@Styleable protected Color focusColor;
|
||||||
@@ -288,6 +293,7 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
|
FlatSelectedTabRepainter.install();
|
||||||
installStyle();
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +324,7 @@ public class FlatTabbedPaneUI
|
|||||||
selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" );
|
selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" );
|
||||||
selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" );
|
selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" );
|
||||||
underlineColor = UIManager.getColor( "TabbedPane.underlineColor" );
|
underlineColor = UIManager.getColor( "TabbedPane.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" );
|
||||||
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
|
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
|
||||||
@@ -385,6 +392,7 @@ public class FlatTabbedPaneUI
|
|||||||
selectedBackground = null;
|
selectedBackground = null;
|
||||||
selectedForeground = null;
|
selectedForeground = null;
|
||||||
underlineColor = null;
|
underlineColor = null;
|
||||||
|
inactiveUnderlineColor = null;
|
||||||
disabledUnderlineColor = null;
|
disabledUnderlineColor = null;
|
||||||
hoverColor = null;
|
hoverColor = null;
|
||||||
focusColor = null;
|
focusColor = null;
|
||||||
@@ -650,7 +658,7 @@ public class FlatTabbedPaneUI
|
|||||||
case "tabIconPlacement": value = parseTabIconPlacement( (String) value ); break;
|
case "tabIconPlacement": value = parseTabIconPlacement( (String) value ); break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Object oldValue = null;
|
Object oldValue;
|
||||||
switch( key ) {
|
switch( key ) {
|
||||||
// BasicTabbedPaneUI
|
// BasicTabbedPaneUI
|
||||||
case "tabInsets": oldValue = tabInsets; tabInsets = (Insets) value; return oldValue;
|
case "tabInsets": oldValue = tabInsets; tabInsets = (Insets) value; return oldValue;
|
||||||
@@ -733,7 +741,6 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
// increase size of repaint region to include part of content border
|
// increase size of repaint region to include part of content border
|
||||||
if( contentSeparatorHeight > 0 &&
|
if( contentSeparatorHeight > 0 &&
|
||||||
getTabType() == TAB_TYPE_CARD &&
|
|
||||||
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
||||||
{
|
{
|
||||||
int sh = scale( contentSeparatorHeight );
|
int sh = scale( contentSeparatorHeight );
|
||||||
@@ -1205,7 +1212,9 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
|
protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
|
||||||
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
|
g.setColor( tabPane.isEnabled()
|
||||||
|
? (isTabbedPaneOrChildFocused() ? underlineColor : inactiveUnderlineColor)
|
||||||
|
: disabledUnderlineColor );
|
||||||
|
|
||||||
// paint underline selection
|
// paint underline selection
|
||||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
||||||
@@ -1236,6 +1245,23 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.2 */
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
protected boolean isTabbedPaneOrChildFocused() {
|
||||||
|
KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
|
||||||
|
Object value = tabPane.getClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER );
|
||||||
|
if( value instanceof Predicate ) {
|
||||||
|
return ((Predicate<JComponent>)value).test( tabPane ) &&
|
||||||
|
FlatUIUtils.isInActiveWindow( tabPane, keyboardFocusManager.getActiveWindow() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Component focusOwner = keyboardFocusManager.getPermanentFocusOwner();
|
||||||
|
return focusOwner != null &&
|
||||||
|
SwingUtilities.isDescendingFrom( focusOwner, tabPane ) &&
|
||||||
|
FlatUIUtils.isInActiveWindow( focusOwner, keyboardFocusManager.getActiveWindow() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually does nearly the same as super.paintContentBorder() but
|
* Actually does nearly the same as super.paintContentBorder() but
|
||||||
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
|
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
|
||||||
@@ -1841,7 +1867,7 @@ public class FlatTabbedPaneUI
|
|||||||
super( direction, arrowType,
|
super( direction, arrowType,
|
||||||
FlatTabbedPaneUI.this.foreground, FlatTabbedPaneUI.this.disabledForeground,
|
FlatTabbedPaneUI.this.foreground, FlatTabbedPaneUI.this.disabledForeground,
|
||||||
null, buttonHoverBackground, null, buttonPressedBackground );
|
null, buttonHoverBackground, null, buttonPressedBackground );
|
||||||
setArrowWidth( 10 );
|
setArrowWidth( 11 );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateStyle() {
|
protected void updateStyle() {
|
||||||
@@ -1983,7 +2009,7 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected JMenuItem createTabMenuItem( int tabIndex ) {
|
protected JMenuItem createTabMenuItem( int tabIndex ) {
|
||||||
// search for tab name in this places
|
// search for tab name in these places
|
||||||
// 1. tab title
|
// 1. tab title
|
||||||
// 2. text of label or text component in custom tab component (including children)
|
// 2. text of label or text component in custom tab component (including children)
|
||||||
// 3. accessible name of tab
|
// 3. accessible name of tab
|
||||||
@@ -2016,7 +2042,7 @@ public class FlatTabbedPaneUI
|
|||||||
menuItem.setOpaque( true );
|
menuItem.setOpaque( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !tabPane.isEnabledAt( tabIndex ) )
|
if( !tabPane.isEnabled() || !tabPane.isEnabledAt( tabIndex ) )
|
||||||
menuItem.setEnabled( false );
|
menuItem.setEnabled( false );
|
||||||
|
|
||||||
menuItem.addActionListener( e -> selectTab( tabIndex ) );
|
menuItem.addActionListener( e -> selectTab( tabIndex ) );
|
||||||
@@ -2412,7 +2438,7 @@ public class FlatTabbedPaneUI
|
|||||||
if( tabPane == null || tabViewport == null )
|
if( tabPane == null || tabViewport == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !scrolled || tabViewport == null )
|
if( !scrolled )
|
||||||
return;
|
return;
|
||||||
scrolled = false;
|
scrolled = false;
|
||||||
|
|
||||||
@@ -2525,9 +2551,7 @@ public class FlatTabbedPaneUI
|
|||||||
setRolloverTab( tabIndex );
|
setRolloverTab( tabIndex );
|
||||||
|
|
||||||
// check whether mouse hit tab close area
|
// check whether mouse hit tab close area
|
||||||
boolean hitClose = isTabClosable( tabIndex )
|
boolean hitClose = isTabClosable( tabIndex ) && getTabCloseHitArea( tabIndex ).contains( x, y );
|
||||||
? getTabCloseHitArea( tabIndex ).contains( x, y )
|
|
||||||
: false;
|
|
||||||
if( e.getID() == MouseEvent.MOUSE_PRESSED )
|
if( e.getID() == MouseEvent.MOUSE_PRESSED )
|
||||||
pressedTabIndex = hitClose ? tabIndex : -1;
|
pressedTabIndex = hitClose ? tabIndex : -1;
|
||||||
setRolloverTabClose( hitClose );
|
setRolloverTabClose( hitClose );
|
||||||
@@ -2550,7 +2574,6 @@ public class FlatTabbedPaneUI
|
|||||||
if( tabIndex == lastTipTabIndex )
|
if( tabIndex == lastTipTabIndex )
|
||||||
return; // closeTip already set
|
return; // closeTip already set
|
||||||
|
|
||||||
if( tabIndex != lastTipTabIndex )
|
|
||||||
restoreTabToolTip();
|
restoreTabToolTip();
|
||||||
|
|
||||||
lastTipTabIndex = tabIndex;
|
lastTipTabIndex = tabIndex;
|
||||||
@@ -3344,4 +3367,77 @@ public class FlatTabbedPaneUI
|
|||||||
delegate.actionPerformed( e );
|
delegate.actionPerformed( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatSelectedTabRepainter -------------------------------------
|
||||||
|
|
||||||
|
private static class FlatSelectedTabRepainter
|
||||||
|
implements PropertyChangeListener//, Runnable
|
||||||
|
{
|
||||||
|
private static FlatSelectedTabRepainter instance;
|
||||||
|
|
||||||
|
private KeyboardFocusManager keyboardFocusManager;
|
||||||
|
|
||||||
|
static void install() {
|
||||||
|
synchronized( FlatSelectedTabRepainter.class ) {
|
||||||
|
if( instance != null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
instance = new FlatSelectedTabRepainter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatSelectedTabRepainter() {
|
||||||
|
keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
keyboardFocusManager.addPropertyChangeListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uninstall() {
|
||||||
|
synchronized( FlatSelectedTabRepainter.class ) {
|
||||||
|
if( instance == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
keyboardFocusManager.removePropertyChangeListener( this );
|
||||||
|
keyboardFocusManager = null;
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
// uninstall if no longer using FlatLaf
|
||||||
|
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) ) {
|
||||||
|
uninstall();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case "permanentFocusOwner":
|
||||||
|
Object oldValue = e.getOldValue();
|
||||||
|
Object newValue = e.getNewValue();
|
||||||
|
if( oldValue instanceof Component )
|
||||||
|
repaintSelectedTabs( (Component) oldValue );
|
||||||
|
if( newValue instanceof Component )
|
||||||
|
repaintSelectedTabs( (Component) newValue );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "activeWindow":
|
||||||
|
repaintSelectedTabs( keyboardFocusManager.getPermanentFocusOwner() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintSelectedTabs( Component c ) {
|
||||||
|
if( c instanceof JTabbedPane )
|
||||||
|
repaintSelectedTab( (JTabbedPane) c );
|
||||||
|
|
||||||
|
while( (c = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c )) != null )
|
||||||
|
repaintSelectedTab( (JTabbedPane) c );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repaintSelectedTab( JTabbedPane tabbedPane ) {
|
||||||
|
TabbedPaneUI ui = tabbedPane.getUI();
|
||||||
|
if( ui instanceof FlatTabbedPaneUI )
|
||||||
|
((FlatTabbedPaneUI) ui).repaintTab( tabbedPane.getSelectedIndex() );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class FlatTableCellBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because this borders are always shared for all tables,
|
* Because this border is always shared for all tables,
|
||||||
* get border specific style from FlatTableUI.
|
* get border specific style from FlatTableUI.
|
||||||
*/
|
*/
|
||||||
static <T> T getStyleFromTableUI( Component c, Function<FlatTableUI, T> f ) {
|
static <T> T getStyleFromTableUI( Component c, Function<FlatTableUI, T> f ) {
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Table.intercellSpacing Dimension
|
* @uiDefault Table.intercellSpacing Dimension
|
||||||
* @uiDefault Table.selectionInactiveBackground Color
|
* @uiDefault Table.selectionInactiveBackground Color
|
||||||
* @uiDefault Table.selectionInactiveForeground Color
|
* @uiDefault Table.selectionInactiveForeground Color
|
||||||
|
* @uiDefault Table.paintOutsideAlternateRows boolean
|
||||||
*
|
*
|
||||||
* <!-- FlatTableCellBorder -->
|
* <!-- FlatTableCellBorder -->
|
||||||
*
|
*
|
||||||
@@ -95,7 +96,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatTableUI
|
public class FlatTableUI
|
||||||
extends BasicTableUI
|
extends BasicTableUI
|
||||||
implements StyleableUI
|
implements StyleableUI, FlatViewportUI.ViewportPainter
|
||||||
{
|
{
|
||||||
protected boolean showHorizontalLines;
|
protected boolean showHorizontalLines;
|
||||||
protected boolean showVerticalLines;
|
protected boolean showVerticalLines;
|
||||||
@@ -288,7 +289,7 @@ public class FlatTableUI
|
|||||||
/**
|
/**
|
||||||
* Toggle selection colors from focused to inactive and vice versa.
|
* Toggle selection colors from focused to inactive and vice versa.
|
||||||
*
|
*
|
||||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||||
*
|
*
|
||||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||||
* already used in applications. Then either the inactive colors are not used,
|
* already used in applications. Then either the inactive colors are not used,
|
||||||
@@ -421,4 +422,38 @@ public class FlatTableUI
|
|||||||
? (viewport != rowHeader)
|
? (viewport != rowHeader)
|
||||||
: (viewport == rowHeader || rowHeader == null);
|
: (viewport == rowHeader || rowHeader == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
@Override
|
||||||
|
public void paintViewport( Graphics g, JComponent c, JViewport viewport ) {
|
||||||
|
int viewportWidth = viewport.getWidth();
|
||||||
|
int viewportHeight = viewport.getHeight();
|
||||||
|
|
||||||
|
// fill viewport background in same color as table background
|
||||||
|
if( viewport.isOpaque() ) {
|
||||||
|
g.setColor( table.getBackground() );
|
||||||
|
g.fillRect( 0, 0, viewportWidth, viewportHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
// paint alternating empty rows
|
||||||
|
boolean paintOutside = UIManager.getBoolean( "Table.paintOutsideAlternateRows" );
|
||||||
|
Color alternateColor;
|
||||||
|
if( paintOutside && (alternateColor = UIManager.getColor( "Table.alternateRowColor" )) != null ) {
|
||||||
|
g.setColor( alternateColor );
|
||||||
|
|
||||||
|
int rowCount = table.getRowCount();
|
||||||
|
|
||||||
|
// paint alternating empty rows below the table
|
||||||
|
int tableHeight = table.getHeight();
|
||||||
|
if( tableHeight < viewportHeight ) {
|
||||||
|
int tableWidth = table.getWidth();
|
||||||
|
int rowHeight = table.getRowHeight();
|
||||||
|
|
||||||
|
for( int y = tableHeight, row = rowCount; y < viewportHeight; y += rowHeight, row++ ) {
|
||||||
|
if( row % 2 != 0 )
|
||||||
|
g.fillRect( 0, y, tableWidth, rowHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ public class FlatTextFieldUI
|
|||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
case PLACEHOLDER_TEXT:
|
case PLACEHOLDER_TEXT:
|
||||||
case COMPONENT_ROUND_RECT:
|
case COMPONENT_ROUND_RECT:
|
||||||
|
case OUTLINE:
|
||||||
case TEXT_FIELD_PADDING:
|
case TEXT_FIELD_PADDING:
|
||||||
c.repaint();
|
c.repaint();
|
||||||
break;
|
break;
|
||||||
@@ -368,7 +369,7 @@ public class FlatTextFieldUI
|
|||||||
if( !(oldBackground instanceof UIResource) )
|
if( !(oldBackground instanceof UIResource) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// do not update background if it currently has a unknown color (assigned from outside)
|
// do not update background if it currently has an unknown color (assigned from outside)
|
||||||
if( oldBackground != background &&
|
if( oldBackground != background &&
|
||||||
oldBackground != disabledBackground &&
|
oldBackground != disabledBackground &&
|
||||||
oldBackground != inactiveBackground &&
|
oldBackground != inactiveBackground &&
|
||||||
@@ -609,7 +610,7 @@ debug*/
|
|||||||
* Returns the rectangle used to paint leading and trailing icons.
|
* Returns the rectangle used to paint leading and trailing icons.
|
||||||
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
||||||
* right margin if the text field has leading or trailing icons or components.
|
* right margin if the text field has leading or trailing icons or components.
|
||||||
* Also the preferred widths of leading and trailing components are removed.
|
* Also, the preferred widths of leading and trailing components are removed.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
@@ -764,6 +765,7 @@ debug*/
|
|||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected JComponent createClearButton() {
|
protected JComponent createClearButton() {
|
||||||
JButton button = new JButton();
|
JButton button = new JButton();
|
||||||
|
button.setName( "TextField.clearButton" );
|
||||||
button.putClientProperty( STYLE_CLASS, "clearButton" );
|
button.putClientProperty( STYLE_CLASS, "clearButton" );
|
||||||
button.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
button.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||||
button.setCursor( Cursor.getDefaultCursor() );
|
button.setCursor( Cursor.getDefaultCursor() );
|
||||||
@@ -825,15 +827,20 @@ debug*/
|
|||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void prepareLeadingOrTrailingComponent( JComponent c ) {
|
protected void prepareLeadingOrTrailingComponent( JComponent c ) {
|
||||||
c.putClientProperty( STYLE_CLASS, "inTextField" );
|
c.putClientProperty( STYLE_CLASS, "inTextField" );
|
||||||
c.setCursor( Cursor.getDefaultCursor() );
|
|
||||||
|
|
||||||
if( c instanceof JButton || c instanceof JToggleButton )
|
if( c instanceof JButton || c instanceof JToggleButton ) {
|
||||||
c.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
c.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||||
else if( c instanceof JToolBar ) {
|
|
||||||
|
if( !c.isCursorSet() )
|
||||||
|
c.setCursor( Cursor.getDefaultCursor() );
|
||||||
|
} else if( c instanceof JToolBar ) {
|
||||||
for( Component child : c.getComponents() ) {
|
for( Component child : c.getComponents() ) {
|
||||||
if( child instanceof JComponent )
|
if( child instanceof JComponent )
|
||||||
((JComponent)child).putClientProperty( STYLE_CLASS, "inTextField" );
|
((JComponent)child).putClientProperty( STYLE_CLASS, "inTextField" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !c.isCursorSet() )
|
||||||
|
c.setCursor( Cursor.getDefaultCursor() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,6 +944,7 @@ debug*/
|
|||||||
((LayoutManager2)delegate).invalidateLayout( target );
|
((LayoutManager2)delegate).invalidateLayout( target );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatDocumentListener -----------------------------------------
|
//---- class FlatDocumentListener -----------------------------------------
|
||||||
|
|
||||||
private class FlatDocumentListener
|
private class FlatDocumentListener
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ public class FlatTitlePane
|
|||||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||||
// but at this time the owner window type is unknown (not yet added)
|
// but at this time the owner window type is unknown (not yet added)
|
||||||
// so we add the iconify/maximize/restore buttons and they are shown
|
// so we add the iconify/maximize/restore buttons, and they are shown
|
||||||
// later in frameStateChanged(), which is invoked from addNotify()
|
// later in frameStateChanged(), which is invoked from addNotify()
|
||||||
|
|
||||||
buttonPanel.add( iconifyButton );
|
buttonPanel.add( iconifyButton );
|
||||||
@@ -420,7 +420,7 @@ public class FlatTitlePane
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this title pane currently has an visible and embedded menubar.
|
* Returns whether this title pane currently has a visible and embedded menubar.
|
||||||
*/
|
*/
|
||||||
protected boolean hasVisibleEmbeddedMenuBar( JMenuBar menuBar ) {
|
protected boolean hasVisibleEmbeddedMenuBar( JMenuBar menuBar ) {
|
||||||
return menuBar != null && menuBar.isVisible() && isMenuBarEmbedded();
|
return menuBar != null && menuBar.isVisible() && isMenuBarEmbedded();
|
||||||
@@ -615,7 +615,7 @@ debug*/
|
|||||||
int maximizedWidth = screenBounds.width;
|
int maximizedWidth = screenBounds.width;
|
||||||
int maximizedHeight = screenBounds.height;
|
int maximizedHeight = screenBounds.height;
|
||||||
|
|
||||||
if( !isMaximizedBoundsFixed() ) {
|
if( SystemInfo.isWindows && !isMaximizedBoundsFixed() ) {
|
||||||
// on Java 8 to 14, maximized x,y are 0,0 based on all screens in a multi-screen environment
|
// on Java 8 to 14, maximized x,y are 0,0 based on all screens in a multi-screen environment
|
||||||
maximizedX = 0;
|
maximizedX = 0;
|
||||||
maximizedY = 0;
|
maximizedY = 0;
|
||||||
@@ -772,7 +772,7 @@ debug*/
|
|||||||
if( horizontalGlue != null ) {
|
if( horizontalGlue != null ) {
|
||||||
// If menu bar is embedded and contains a horizontal glue component,
|
// If menu bar is embedded and contains a horizontal glue component,
|
||||||
// then split the hit test spot into two spots so that
|
// then split the hit test spot into two spots so that
|
||||||
// the glue component area can used to move the window.
|
// the glue component area can be used to move the window.
|
||||||
|
|
||||||
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
|
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
|
||||||
int x2 = glueLocation.x + horizontalGlue.getWidth();
|
int x2 = glueLocation.x + horizontalGlue.getWidth();
|
||||||
@@ -854,7 +854,7 @@ debug*/
|
|||||||
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) )
|
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) )
|
||||||
insets.bottom += UIScale.scale( 1 );
|
insets.bottom += UIScale.scale( 1 );
|
||||||
|
|
||||||
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||||
insets = FlatUIUtils.addInsets( insets, WindowTopBorder.getInstance().getBorderInsets() );
|
insets = FlatUIUtils.addInsets( insets, WindowTopBorder.getInstance().getBorderInsets() );
|
||||||
|
|
||||||
return insets;
|
return insets;
|
||||||
@@ -873,7 +873,7 @@ debug*/
|
|||||||
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||||
WindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
|
WindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,9 +883,7 @@ debug*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isWindowMaximized( Component c ) {
|
protected boolean isWindowMaximized( Component c ) {
|
||||||
return window instanceof Frame
|
return window instanceof Frame && (((Frame) window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||||
? (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
|
|
||||||
: false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -911,7 +909,7 @@ debug*/
|
|||||||
boolean center = hasEmbeddedMenuBar ? centerTitleIfMenuBarEmbedded : centerTitle;
|
boolean center = hasEmbeddedMenuBar ? centerTitleIfMenuBarEmbedded : centerTitle;
|
||||||
if( center ) {
|
if( center ) {
|
||||||
// If window is wide enough, center title within window bounds.
|
// If window is wide enough, center title within window bounds.
|
||||||
// Otherwise leave it centered within free space (label bounds).
|
// Otherwise, leave it centered within free space (label bounds).
|
||||||
int centeredTextX = ((l.getParent().getWidth() - textWidth) / 2) - l.getX();
|
int centeredTextX = ((l.getParent().getWidth() - textWidth) / 2) - l.getX();
|
||||||
if( centeredTextX >= gap && centeredTextX + textWidth <= labelWidth - gap )
|
if( centeredTextX >= gap && centeredTextX + textWidth <= labelWidth - gap )
|
||||||
textX = centeredTextX;
|
textX = centeredTextX;
|
||||||
@@ -966,7 +964,7 @@ debug*/
|
|||||||
activeChanged( true );
|
activeChanged( true );
|
||||||
updateNativeTitleBarHeightAndHitTestSpots();
|
updateNativeTitleBarHeightAndHitTestSpots();
|
||||||
|
|
||||||
if( hasNativeCustomDecoration() )
|
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() )
|
||||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||||
|
|
||||||
repaintWindowBorder();
|
repaintWindowBorder();
|
||||||
@@ -977,7 +975,7 @@ debug*/
|
|||||||
activeChanged( false );
|
activeChanged( false );
|
||||||
updateNativeTitleBarHeightAndHitTestSpots();
|
updateNativeTitleBarHeightAndHitTestSpots();
|
||||||
|
|
||||||
if( hasNativeCustomDecoration() )
|
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() )
|
||||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||||
|
|
||||||
repaintWindowBorder();
|
repaintWindowBorder();
|
||||||
@@ -1018,6 +1016,9 @@ debug*/
|
|||||||
if( window == null )
|
if( window == null )
|
||||||
return; // should newer occur
|
return; // should newer occur
|
||||||
|
|
||||||
|
if( !SwingUtilities.isLeftMouseButton( e ) )
|
||||||
|
return;
|
||||||
|
|
||||||
dragOffset = SwingUtilities.convertPoint( FlatTitlePane.this, e.getPoint(), window );
|
dragOffset = SwingUtilities.convertPoint( FlatTitlePane.this, e.getPoint(), window );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1032,6 +1033,9 @@ debug*/
|
|||||||
if( window == null )
|
if( window == null )
|
||||||
return; // should newer occur
|
return; // should newer occur
|
||||||
|
|
||||||
|
if( !SwingUtilities.isLeftMouseButton( e ) )
|
||||||
|
return;
|
||||||
|
|
||||||
if( hasNativeCustomDecoration() )
|
if( hasNativeCustomDecoration() )
|
||||||
return; // do nothing if having native window border
|
return; // do nothing if having native window border
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,8 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.*;
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.JToggleButton;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
@@ -52,15 +48,29 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault ToggleButton.iconTextGap int
|
* @uiDefault ToggleButton.iconTextGap int
|
||||||
* @uiDefault ToggleButton.startBackground Color optional; if set, a gradient paint is used and ToggleButton.background is ignored
|
* @uiDefault ToggleButton.startBackground Color optional; if set, a gradient paint is used and ToggleButton.background is ignored
|
||||||
* @uiDefault ToggleButton.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault ToggleButton.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault ToggleButton.pressedBackground Color
|
* @uiDefault ToggleButton.focusedBackground Color optional
|
||||||
|
* @uiDefault ToggleButton.focusedForeground Color optional
|
||||||
|
* @uiDefault ToggleButton.hoverBackground Color optional
|
||||||
|
* @uiDefault ToggleButton.hoverForeground Color optional
|
||||||
|
* @uiDefault ToggleButton.pressedBackground Color optional
|
||||||
|
* @uiDefault ToggleButton.pressedForeground Color optional
|
||||||
* @uiDefault ToggleButton.selectedBackground Color
|
* @uiDefault ToggleButton.selectedBackground Color
|
||||||
* @uiDefault ToggleButton.selectedForeground Color
|
* @uiDefault ToggleButton.selectedForeground Color
|
||||||
* @uiDefault ToggleButton.disabledBackground Color optional
|
* @uiDefault ToggleButton.disabledBackground Color optional
|
||||||
* @uiDefault ToggleButton.disabledText Color
|
* @uiDefault ToggleButton.disabledText Color
|
||||||
* @uiDefault ToggleButton.disabledSelectedBackground Color
|
* @uiDefault ToggleButton.disabledSelectedBackground Color
|
||||||
|
* @uiDefault ToggleButton.disabledSelectedForeground Color optional
|
||||||
|
* @uiDefault Button.paintShadow boolean default is false
|
||||||
|
* @uiDefault Button.shadowWidth int default is 2
|
||||||
|
* @uiDefault Button.shadowColor Color optional
|
||||||
* @uiDefault ToggleButton.toolbar.hoverBackground Color
|
* @uiDefault ToggleButton.toolbar.hoverBackground Color
|
||||||
|
* @uiDefault ToggleButton.toolbar.hoverForeground Color optional
|
||||||
* @uiDefault ToggleButton.toolbar.pressedBackground Color
|
* @uiDefault ToggleButton.toolbar.pressedBackground Color
|
||||||
|
* @uiDefault ToggleButton.toolbar.pressedForeground Color optional
|
||||||
* @uiDefault ToggleButton.toolbar.selectedBackground Color
|
* @uiDefault ToggleButton.toolbar.selectedBackground Color
|
||||||
|
* @uiDefault ToggleButton.toolbar.selectedForeground Color optional
|
||||||
|
* @uiDefault ToggleButton.toolbar.disabledSelectedBackground Color optional
|
||||||
|
* @uiDefault ToggleButton.toolbar.disabledSelectedForeground Color optional
|
||||||
*
|
*
|
||||||
* <!-- FlatToggleButtonUI -->
|
* <!-- FlatToggleButtonUI -->
|
||||||
*
|
*
|
||||||
@@ -68,8 +78,11 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault ToggleButton.tab.underlineColor Color
|
* @uiDefault ToggleButton.tab.underlineColor Color
|
||||||
* @uiDefault ToggleButton.tab.disabledUnderlineColor Color
|
* @uiDefault ToggleButton.tab.disabledUnderlineColor Color
|
||||||
* @uiDefault ToggleButton.tab.selectedBackground Color optional
|
* @uiDefault ToggleButton.tab.selectedBackground Color optional
|
||||||
|
* @uiDefault ToggleButton.tab.selectedForeground Color optional
|
||||||
* @uiDefault ToggleButton.tab.hoverBackground Color
|
* @uiDefault ToggleButton.tab.hoverBackground Color
|
||||||
|
* @uiDefault ToggleButton.tab.hoverForeground Color optional
|
||||||
* @uiDefault ToggleButton.tab.focusBackground Color
|
* @uiDefault ToggleButton.tab.focusBackground Color
|
||||||
|
* @uiDefault ToggleButton.tab.focusForeground Color optional
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -81,8 +94,11 @@ public class FlatToggleButtonUI
|
|||||||
@Styleable(dot=true) protected Color tabUnderlineColor;
|
@Styleable(dot=true) protected Color tabUnderlineColor;
|
||||||
@Styleable(dot=true) protected Color tabDisabledUnderlineColor;
|
@Styleable(dot=true) protected Color tabDisabledUnderlineColor;
|
||||||
@Styleable(dot=true) protected Color tabSelectedBackground;
|
@Styleable(dot=true) protected Color tabSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color tabSelectedForeground;
|
||||||
@Styleable(dot=true) protected Color tabHoverBackground;
|
@Styleable(dot=true) protected Color tabHoverBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color tabHoverForeground;
|
||||||
@Styleable(dot=true) protected Color tabFocusBackground;
|
@Styleable(dot=true) protected Color tabFocusBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color tabFocusForeground;
|
||||||
|
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
|
|
||||||
@@ -115,8 +131,11 @@ public class FlatToggleButtonUI
|
|||||||
tabUnderlineColor = UIManager.getColor( "ToggleButton.tab.underlineColor" );
|
tabUnderlineColor = UIManager.getColor( "ToggleButton.tab.underlineColor" );
|
||||||
tabDisabledUnderlineColor = UIManager.getColor( "ToggleButton.tab.disabledUnderlineColor" );
|
tabDisabledUnderlineColor = UIManager.getColor( "ToggleButton.tab.disabledUnderlineColor" );
|
||||||
tabSelectedBackground = UIManager.getColor( "ToggleButton.tab.selectedBackground" );
|
tabSelectedBackground = UIManager.getColor( "ToggleButton.tab.selectedBackground" );
|
||||||
|
tabSelectedForeground = UIManager.getColor( "ToggleButton.tab.selectedForeground" );
|
||||||
tabHoverBackground = UIManager.getColor( "ToggleButton.tab.hoverBackground" );
|
tabHoverBackground = UIManager.getColor( "ToggleButton.tab.hoverBackground" );
|
||||||
|
tabHoverForeground = UIManager.getColor( "ToggleButton.tab.hoverForeground" );
|
||||||
tabFocusBackground = UIManager.getColor( "ToggleButton.tab.focusBackground" );
|
tabFocusBackground = UIManager.getColor( "ToggleButton.tab.focusBackground" );
|
||||||
|
tabFocusForeground = UIManager.getColor( "ToggleButton.tab.focusForeground" );
|
||||||
|
|
||||||
defaults_initialized = true;
|
defaults_initialized = true;
|
||||||
}
|
}
|
||||||
@@ -143,6 +162,7 @@ public class FlatToggleButtonUI
|
|||||||
b.repaint();
|
b.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TAB_BUTTON_UNDERLINE_PLACEMENT:
|
||||||
case TAB_BUTTON_UNDERLINE_HEIGHT:
|
case TAB_BUTTON_UNDERLINE_HEIGHT:
|
||||||
case TAB_BUTTON_UNDERLINE_COLOR:
|
case TAB_BUTTON_UNDERLINE_COLOR:
|
||||||
case TAB_BUTTON_SELECTED_BACKGROUND:
|
case TAB_BUTTON_SELECTED_BACKGROUND:
|
||||||
@@ -164,11 +184,7 @@ public class FlatToggleButtonUI
|
|||||||
@Override
|
@Override
|
||||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
Map<String, Class<?>> infos = super.getStyleableInfos( c );
|
Map<String, Class<?>> infos = super.getStyleableInfos( c );
|
||||||
Iterator<String> it = infos.keySet().iterator();
|
infos.keySet().removeIf( s -> s.startsWith( "help." ) );
|
||||||
while( it.hasNext() ) {
|
|
||||||
if( it.next().startsWith( "help." ) )
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
return infos;
|
return infos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,13 +217,42 @@ public class FlatToggleButtonUI
|
|||||||
|
|
||||||
// paint underline if selected
|
// paint underline if selected
|
||||||
if( selected ) {
|
if( selected ) {
|
||||||
int underlineHeight = UIScale.scale( clientPropertyInt( c, TAB_BUTTON_UNDERLINE_HEIGHT, tabUnderlineHeight ) );
|
int underlineThickness = UIScale.scale( clientPropertyInt( c, TAB_BUTTON_UNDERLINE_HEIGHT, tabUnderlineHeight ) );
|
||||||
g.setColor( c.isEnabled()
|
g.setColor( c.isEnabled()
|
||||||
? clientPropertyColor( c, TAB_BUTTON_UNDERLINE_COLOR, tabUnderlineColor )
|
? clientPropertyColor( c, TAB_BUTTON_UNDERLINE_COLOR, tabUnderlineColor )
|
||||||
: tabDisabledUnderlineColor );
|
: tabDisabledUnderlineColor );
|
||||||
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
|
int placement = clientPropertyInt( c, TAB_BUTTON_UNDERLINE_PLACEMENT, SwingConstants.BOTTOM );
|
||||||
|
switch (placement) {
|
||||||
|
case SwingConstants.TOP:
|
||||||
|
g.fillRect( 0, 0, width, underlineThickness );
|
||||||
|
break;
|
||||||
|
case SwingConstants.LEFT:
|
||||||
|
g.fillRect( 0, 0, underlineThickness, height );
|
||||||
|
break;
|
||||||
|
case SwingConstants.RIGHT:
|
||||||
|
g.fillRect( width - underlineThickness, 0, underlineThickness, height );
|
||||||
|
break;
|
||||||
|
case SwingConstants.BOTTOM:
|
||||||
|
default:
|
||||||
|
g.fillRect( 0, height - underlineThickness, width, underlineThickness );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
super.paintBackground( g, c );
|
super.paintBackground( g, c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Color getForeground( JComponent c ) {
|
||||||
|
if( isTabButton( c ) ) {
|
||||||
|
if( !c.isEnabled() )
|
||||||
|
return disabledText;
|
||||||
|
|
||||||
|
if( tabSelectedForeground != null && ((AbstractButton)c).isSelected() )
|
||||||
|
return tabSelectedForeground;
|
||||||
|
|
||||||
|
return buttonStateColor( c, c.getForeground(), disabledText,
|
||||||
|
tabFocusForeground, tabHoverForeground, null );
|
||||||
|
} else
|
||||||
|
return super.getForeground( c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -31,6 +32,7 @@ import javax.swing.SwingConstants;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
|
import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
|
||||||
|
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;
|
||||||
@@ -47,7 +49,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
*/
|
*/
|
||||||
public class FlatToolBarSeparatorUI
|
public class FlatToolBarSeparatorUI
|
||||||
extends BasicToolBarSeparatorUI
|
extends BasicToolBarSeparatorUI
|
||||||
implements StyleableUI
|
implements StyleableUI, PropertyChangeListener
|
||||||
{
|
{
|
||||||
private static final int LINE_WIDTH = 1;
|
private static final int LINE_WIDTH = 1;
|
||||||
|
|
||||||
@@ -56,7 +58,6 @@ public class FlatToolBarSeparatorUI
|
|||||||
|
|
||||||
private final boolean shared;
|
private final boolean shared;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
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 ) {
|
||||||
@@ -105,20 +106,23 @@ public class FlatToolBarSeparatorUI
|
|||||||
protected void installListeners( JSeparator s ) {
|
protected void installListeners( JSeparator s ) {
|
||||||
super.installListeners( s );
|
super.installListeners( s );
|
||||||
|
|
||||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
s.addPropertyChangeListener( this );
|
||||||
s, () -> stylePropertyChange( s ), null );
|
|
||||||
s.addPropertyChangeListener( propertyChangeListener );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void uninstallListeners( JSeparator s ) {
|
protected void uninstallListeners( JSeparator s ) {
|
||||||
super.uninstallListeners( s );
|
super.uninstallListeners( s );
|
||||||
|
|
||||||
s.removePropertyChangeListener( propertyChangeListener );
|
s.removePropertyChangeListener( this );
|
||||||
propertyChangeListener = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stylePropertyChange( JSeparator s ) {
|
/** @since 2.0.1 */
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case FlatClientProperties.STYLE:
|
||||||
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
|
JSeparator s = (JSeparator) e.getSource();
|
||||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||||
// unshare component UI if necessary
|
// unshare component UI if necessary
|
||||||
// updateUI() invokes installStyle() from installUI()
|
// updateUI() invokes installStyle() from installUI()
|
||||||
@@ -127,6 +131,8 @@ public class FlatToolBarSeparatorUI
|
|||||||
installStyle( s );
|
installStyle( s );
|
||||||
s.revalidate();
|
s.revalidate();
|
||||||
s.repaint();
|
s.repaint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -256,11 +256,15 @@ public class FlatToolBarUI
|
|||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = focusedCompIndex + add; i != focusedCompIndex; i += add ) {
|
int i = focusedCompIndex;
|
||||||
|
for(;;) {
|
||||||
|
i += add;
|
||||||
if( i < 0 )
|
if( i < 0 )
|
||||||
i = count - 1;
|
i = count - 1;
|
||||||
else if( i >= count )
|
else if( i >= count )
|
||||||
i = 0;
|
i = 0;
|
||||||
|
if( i == focusedCompIndex )
|
||||||
|
break;
|
||||||
|
|
||||||
Component c = toolBar.getComponentAtIndex( i );
|
Component c = toolBar.getComponentAtIndex( i );
|
||||||
if( canBeFocusOwner( c ) ) {
|
if( canBeFocusOwner( c ) ) {
|
||||||
@@ -282,7 +286,7 @@ public class FlatToolBarUI
|
|||||||
return comboBox.getUI().isFocusTraversable( comboBox );
|
return comboBox.getUI().isFocusTraversable( comboBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether component has a empty input map to skip components that
|
// check whether component has an empty input map to skip components that
|
||||||
// are focusable, but do nothing when focused (e.g. JLabel)
|
// are focusable, but do nothing when focused (e.g. JLabel)
|
||||||
// see LayoutFocusTraversalPolicy.accept()
|
// see LayoutFocusTraversalPolicy.accept()
|
||||||
if( c instanceof JComponent ) {
|
if( c instanceof JComponent ) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.FontMetrics;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -49,9 +50,8 @@ import com.formdev.flatlaf.util.StringUtils;
|
|||||||
*/
|
*/
|
||||||
public class FlatToolTipUI
|
public class FlatToolTipUI
|
||||||
extends BasicToolTipUI
|
extends BasicToolTipUI
|
||||||
|
implements PropertyChangeListener
|
||||||
{
|
{
|
||||||
private static PropertyChangeListener sharedPropertyChangedListener;
|
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return FlatUIUtils.createSharedUI( FlatToolTipUI.class, FlatToolTipUI::new );
|
return FlatUIUtils.createSharedUI( FlatToolTipUI.class, FlatToolTipUI::new );
|
||||||
}
|
}
|
||||||
@@ -68,24 +68,24 @@ public class FlatToolTipUI
|
|||||||
protected void installListeners( JComponent c ) {
|
protected void installListeners( JComponent c ) {
|
||||||
super.installListeners( c );
|
super.installListeners( c );
|
||||||
|
|
||||||
if( sharedPropertyChangedListener == null ) {
|
c.addPropertyChangeListener( this );
|
||||||
sharedPropertyChangedListener = e -> {
|
|
||||||
String name = e.getPropertyName();
|
|
||||||
if( name == "tiptext" || name == "font" || name == "foreground" ) {
|
|
||||||
JToolTip toolTip = (JToolTip) e.getSource();
|
|
||||||
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c.addPropertyChangeListener( sharedPropertyChangedListener );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void uninstallListeners( JComponent c ) {
|
protected void uninstallListeners( JComponent c ) {
|
||||||
super.uninstallListeners( c );
|
super.uninstallListeners( c );
|
||||||
|
|
||||||
c.removePropertyChangeListener( sharedPropertyChangedListener );
|
c.removePropertyChangeListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.0.1 */
|
||||||
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
String name = e.getPropertyName();
|
||||||
|
if( name == "tiptext" || name == "font" || name == "foreground" ) {
|
||||||
|
JToolTip toolTip = (JToolTip) e.getSource();
|
||||||
|
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class FlatUIUtils
|
|||||||
public static final boolean MAC_USE_QUARTZ = Boolean.getBoolean( "apple.awt.graphics.UseQuartz" );
|
public static final boolean MAC_USE_QUARTZ = Boolean.getBoolean( "apple.awt.graphics.UseQuartz" );
|
||||||
|
|
||||||
private static boolean useSharedUIs = true;
|
private static boolean useSharedUIs = true;
|
||||||
private static WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
private static final WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
||||||
|
|
||||||
public static Rectangle addInsets( Rectangle r, Insets insets ) {
|
public static Rectangle addInsets( Rectangle r, Insets insets ) {
|
||||||
return new Rectangle(
|
return new Rectangle(
|
||||||
@@ -245,7 +245,7 @@ public class FlatUIUtils
|
|||||||
isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
|
isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isInActiveWindow( Component c, Window activeWindow ) {
|
static boolean isInActiveWindow( Component c, Window activeWindow ) {
|
||||||
Window window = SwingUtilities.windowForComponent( c );
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
return window == activeWindow ||
|
return window == activeWindow ||
|
||||||
(window != null && window.getType() == Window.Type.POPUP && window.getOwner() == activeWindow);
|
(window != null && window.getType() == Window.Type.POPUP && window.getOwner() == activeWindow);
|
||||||
@@ -777,8 +777,8 @@ public class FlatUIUtils
|
|||||||
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
|
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
|
||||||
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
|
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
|
||||||
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
|
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
|
||||||
* @param xOffset a offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
* @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||||
* @param yOffset a offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
* @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||||
*
|
*
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
@@ -786,13 +786,15 @@ public class FlatUIUtils
|
|||||||
int direction, boolean chevron, int arrowSize, float xOffset, float yOffset )
|
int direction, boolean chevron, int arrowSize, float xOffset, float yOffset )
|
||||||
{
|
{
|
||||||
// compute arrow width/height
|
// compute arrow width/height
|
||||||
int aw = UIScale.scale( arrowSize + (chevron ? 0 : 1) );
|
// - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5)
|
||||||
int ah = UIScale.scale( (arrowSize / 2) + (chevron ? 0 : 1) );
|
// - make triangle arrows one pixel taller (and round height up) to make them look stronger
|
||||||
|
float aw = UIScale.scale( arrowSize + (chevron ? -1 : 0) );
|
||||||
|
float ah = chevron ? (aw / 2) : UIScale.scale( (arrowSize / 2) + 1 );
|
||||||
|
|
||||||
// rotate arrow width/height for horizontal directions
|
// rotate arrow width/height for horizontal directions
|
||||||
boolean vert = (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH);
|
boolean vert = (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH);
|
||||||
if( !vert ) {
|
if( !vert ) {
|
||||||
int temp = aw;
|
float temp = aw;
|
||||||
aw = ah;
|
aw = ah;
|
||||||
ah = temp;
|
ah = temp;
|
||||||
}
|
}
|
||||||
@@ -804,19 +806,19 @@ public class FlatUIUtils
|
|||||||
// compute arrow location
|
// compute arrow location
|
||||||
float ox = ((width - (aw + extra)) / 2f) + UIScale.scale( xOffset );
|
float ox = ((width - (aw + extra)) / 2f) + UIScale.scale( xOffset );
|
||||||
float oy = ((height - (ah + extra)) / 2f) + UIScale.scale( yOffset );
|
float oy = ((height - (ah + extra)) / 2f) + UIScale.scale( yOffset );
|
||||||
int ax = x + ((direction == SwingConstants.WEST) ? -Math.round( -ox ) : Math.round( ox ));
|
float ax = x + ((direction == SwingConstants.WEST) ? -Math.round( -(ox + aw) ) - aw : Math.round( ox ));
|
||||||
int ay = y + ((direction == SwingConstants.NORTH) ? -Math.round( -oy ) : Math.round( oy ));
|
float ay = y + ((direction == SwingConstants.NORTH) ? -Math.round( -(oy + ah) ) - ah : Math.round( oy ));
|
||||||
|
|
||||||
// paint arrow
|
// paint arrow
|
||||||
g.translate( ax, ay );
|
g.translate( ax, ay );
|
||||||
/*debug
|
/*debug
|
||||||
debugPaintArrow( g, Color.red, vert, aw + extra, ah + extra );
|
debugPaintArrow( g, Color.red, vert, Math.round( aw + extra ), Math.round( ah + extra ) );
|
||||||
debug*/
|
debug*/
|
||||||
Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
|
Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
Stroke oldStroke = g.getStroke();
|
Stroke oldStroke = g.getStroke();
|
||||||
g.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
g.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
||||||
g.draw( arrowShape );
|
drawShapePure( g, arrowShape );
|
||||||
g.setStroke( oldStroke );
|
g.setStroke( oldStroke );
|
||||||
} else {
|
} else {
|
||||||
// triangle
|
// triangle
|
||||||
@@ -828,7 +830,7 @@ debug*/
|
|||||||
/**
|
/**
|
||||||
* Creates a chevron or triangle arrow shape for the given direction and size.
|
* Creates a chevron or triangle arrow shape for the given direction and size.
|
||||||
* <p>
|
* <p>
|
||||||
* The chevron shape is a open path that can be painted with {@link Graphics2D#draw(Shape)}.
|
* The chevron shape is an open path that can be painted with {@link Graphics2D#draw(Shape)}.
|
||||||
* The triangle shape is a close path that can be painted with {@link Graphics2D#fill(Shape)}.
|
* The triangle shape is a close path that can be painted with {@link Graphics2D#fill(Shape)}.
|
||||||
*
|
*
|
||||||
* @param direction the arrow direction ({@link SwingConstants#NORTH}, {@link SwingConstants#SOUTH}
|
* @param direction the arrow direction ({@link SwingConstants#NORTH}, {@link SwingConstants#SOUTH}
|
||||||
@@ -880,7 +882,7 @@ debug*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a open or closed path for the given points.
|
* Creates an open or closed path for the given points.
|
||||||
*/
|
*/
|
||||||
public static Path2D createPath( boolean close, double... points ) {
|
public static Path2D createPath( boolean close, double... points ) {
|
||||||
Path2D path = new Path2D.Float();
|
Path2D path = new Path2D.Float();
|
||||||
@@ -892,6 +894,23 @@ debug*/
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the given shape with disabled stroke normalization.
|
||||||
|
* The x/y coordinates of the shape are translated by a half pixel.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public static void drawShapePure( Graphics2D g, Shape shape ) {
|
||||||
|
Object oldStrokeControl = g.getRenderingHint( RenderingHints.KEY_STROKE_CONTROL );
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
g.translate( 0.5, 0.5 );
|
||||||
|
g.draw( shape );
|
||||||
|
g.translate( -0.5, -0.5 );
|
||||||
|
|
||||||
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, oldStrokeControl );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given string at the specified location.
|
* Draws the given string at the specified location.
|
||||||
* The provided component is used to query text properties and anti-aliasing hints.
|
* The provided component is used to query text properties and anti-aliasing hints.
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.JViewport;
|
import javax.swing.JViewport;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicViewportUI;
|
import javax.swing.plaf.basic.BasicViewportUI;
|
||||||
@@ -43,15 +43,28 @@ public class FlatViewportUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
Component view = ((JViewport)c).getView();
|
super.paint( g, c );
|
||||||
if( c.isOpaque() && view instanceof JTable ) {
|
|
||||||
// paint viewport background in same color as table background
|
|
||||||
g.setColor( view.getBackground() );
|
|
||||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
|
||||||
|
|
||||||
paint( g, c );
|
Component view = ((JViewport)c).getView();
|
||||||
} else
|
if( view instanceof JComponent ) {
|
||||||
super.update( g, c );
|
try {
|
||||||
|
Method m = view.getClass().getMethod( "getUI" );
|
||||||
|
Object ui = m.invoke( view );
|
||||||
|
if( ui instanceof ViewportPainter )
|
||||||
|
((ViewportPainter)ui).paintViewport( g, (JComponent) view, (JViewport) c );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface ViewportPainter ------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.3
|
||||||
|
*/
|
||||||
|
public interface ViewportPainter {
|
||||||
|
void paintViewport( Graphics g, JComponent c, JViewport viewport );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.awt.Dialog;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
@@ -42,7 +43,9 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JInternalFrame;
|
import javax.swing.JInternalFrame;
|
||||||
import javax.swing.JLayeredPane;
|
import javax.swing.JLayeredPane;
|
||||||
import javax.swing.JRootPane;
|
import javax.swing.JRootPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,8 +234,15 @@ public abstract class FlatWindowResizer
|
|||||||
{
|
{
|
||||||
protected Window window;
|
protected Window window;
|
||||||
|
|
||||||
|
private final boolean limitResizeToScreenBounds;
|
||||||
|
|
||||||
public WindowResizer( JRootPane rootPane ) {
|
public WindowResizer( JRootPane rootPane ) {
|
||||||
super( rootPane );
|
super( rootPane );
|
||||||
|
|
||||||
|
// On Linux, limit window resizing to screen bounds because otherwise
|
||||||
|
// there would be a strange effect when the mouse is moved over a sidebar
|
||||||
|
// while resizing and the opposite window side is also resized.
|
||||||
|
limitResizeToScreenBounds = SystemInfo.isLinux;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -289,11 +299,19 @@ public abstract class FlatWindowResizer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean limitToParentBounds() {
|
protected boolean limitToParentBounds() {
|
||||||
return false;
|
return limitResizeToScreenBounds && window != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Rectangle getParentBounds() {
|
protected Rectangle getParentBounds() {
|
||||||
|
if( limitResizeToScreenBounds && window != null ) {
|
||||||
|
GraphicsConfiguration gc = window.getGraphicsConfiguration();
|
||||||
|
Rectangle bounds = gc.getBounds();
|
||||||
|
Insets insets = window.getToolkit().getScreenInsets( gc );
|
||||||
|
return new Rectangle( bounds.x + insets.left, bounds.y + insets.top,
|
||||||
|
bounds.width - insets.left - insets.right,
|
||||||
|
bounds.height - insets.top - insets.bottom );
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +403,7 @@ public abstract class FlatWindowResizer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Rectangle getParentBounds() {
|
protected Rectangle getParentBounds() {
|
||||||
return getFrame().getParent().getBounds();
|
return new Rectangle( getFrame().getParent().getSize() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -504,7 +522,7 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed( MouseEvent e ) {
|
public void mousePressed( MouseEvent e ) {
|
||||||
if( !isWindowResizable() )
|
if( !SwingUtilities.isLeftMouseButton( e ) || !isWindowResizable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int xOnScreen = e.getXOnScreen();
|
int xOnScreen = e.getXOnScreen();
|
||||||
@@ -533,7 +551,7 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
if( !isWindowResizable() )
|
if( !SwingUtilities.isLeftMouseButton( e ) || !isWindowResizable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dragLeftOffset = dragRightOffset = dragTopOffset = dragBottomOffset = 0;
|
dragLeftOffset = dragRightOffset = dragTopOffset = dragBottomOffset = 0;
|
||||||
@@ -559,7 +577,7 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseDragged( MouseEvent e ) {
|
public void mouseDragged( MouseEvent e ) {
|
||||||
if( !isWindowResizable() )
|
if( !SwingUtilities.isLeftMouseButton( e ) || !isWindowResizable() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int xOnScreen = e.getXOnScreen();
|
int xOnScreen = e.getXOnScreen();
|
||||||
@@ -579,8 +597,8 @@ debug*/
|
|||||||
// top
|
// top
|
||||||
if( resizeDir == N_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR ) {
|
if( resizeDir == N_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR ) {
|
||||||
newBounds.y = yOnScreen - dragTopOffset;
|
newBounds.y = yOnScreen - dragTopOffset;
|
||||||
if( limitToParentBounds() && newBounds.y < 0 )
|
if( limitToParentBounds() )
|
||||||
newBounds.y = 0;
|
newBounds.y = Math.max( newBounds.y, getParentBounds().y );
|
||||||
newBounds.height += (oldBounds.y - newBounds.y);
|
newBounds.height += (oldBounds.y - newBounds.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,8 +615,8 @@ debug*/
|
|||||||
// left
|
// left
|
||||||
if( resizeDir == W_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR ) {
|
if( resizeDir == W_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR ) {
|
||||||
newBounds.x = xOnScreen - dragLeftOffset;
|
newBounds.x = xOnScreen - dragLeftOffset;
|
||||||
if( limitToParentBounds() && newBounds.x < 0 )
|
if( limitToParentBounds() )
|
||||||
newBounds.x = 0;
|
newBounds.x = Math.max( newBounds.x, getParentBounds().x );
|
||||||
newBounds.width += (oldBounds.x - newBounds.x);
|
newBounds.width += (oldBounds.x - newBounds.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import javax.swing.event.ChangeEvent;
|
|||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import javax.swing.event.EventListenerList;
|
import javax.swing.event.EventListenerList;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.NativeLibrary;
|
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -82,7 +81,6 @@ class FlatWindowsNativeWindowBorder
|
|||||||
private Color colorizationColor;
|
private Color colorizationColor;
|
||||||
private int colorizationColorBalance;
|
private int colorizationColorBalance;
|
||||||
|
|
||||||
private static NativeLibrary nativeLibrary;
|
|
||||||
private static FlatWindowsNativeWindowBorder instance;
|
private static FlatWindowsNativeWindowBorder instance;
|
||||||
|
|
||||||
static FlatNativeWindowBorder.Provider getInstance() {
|
static FlatNativeWindowBorder.Provider getInstance() {
|
||||||
@@ -94,35 +92,8 @@ class FlatWindowsNativeWindowBorder
|
|||||||
if( !SystemInfo.isX86 && !SystemInfo.isX86_64 )
|
if( !SystemInfo.isX86 && !SystemInfo.isX86_64 )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// load native library
|
|
||||||
if( nativeLibrary == null ) {
|
|
||||||
if( !SystemInfo.isJava_9_orLater ) {
|
|
||||||
// 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 does not have this problem.
|
|
||||||
try {
|
|
||||||
System.loadLibrary( "jawt" );
|
|
||||||
} catch( UnsatisfiedLinkError ex ) {
|
|
||||||
// log error only if native library jawt.dll not already loaded
|
|
||||||
String message = ex.getMessage();
|
|
||||||
if( message == null || !message.contains( "already loaded in another classloader" ) )
|
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
|
||||||
} catch( Exception ex ) {
|
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String libraryName = "com/formdev/flatlaf/natives/flatlaf-windows-x86";
|
|
||||||
if( SystemInfo.isX86_64 )
|
|
||||||
libraryName += "_64";
|
|
||||||
|
|
||||||
nativeLibrary = new NativeLibrary( libraryName, null, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether native library was successfully loaded
|
// check whether native library was successfully loaded
|
||||||
if( !nativeLibrary.isLoaded() )
|
if( !FlatNativeLibrary.isLoaded() )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// create new instance
|
// create new instance
|
||||||
@@ -140,7 +111,7 @@ class FlatWindowsNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the window whether the application wants use custom decorations.
|
* Tell the window whether the application wants to use custom decorations.
|
||||||
* If {@code true}, the Windows 10 title bar is hidden (including minimize,
|
* If {@code true}, the Windows 10 title bar is hidden (including minimize,
|
||||||
* maximize and close buttons), but not the resize borders (including drop shadow).
|
* maximize and close buttons), but not the resize borders (including drop shadow).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ public class JBRCustomDecorations
|
|||||||
@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 ) {
|
||||||
Window window = SwingUtilities.windowForComponent( c );
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
boolean active = (window != null) ? window.isActive() : false;
|
boolean active = window != null && window.isActive();
|
||||||
|
|
||||||
// paint top border
|
// paint top border
|
||||||
// - in light themes
|
// - in light themes
|
||||||
@@ -298,7 +298,7 @@ public class JBRCustomDecorations
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
g.drawRect( x, y, width - 1, 0 );
|
g.fillRect( x, y, width, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void repaintBorder( Component c ) {
|
void repaintBorder( Component c ) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import com.formdev.flatlaf.util.Animator.Interpolator;
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* Animation works only if the component passed to {@link #paintIcon(Component, Graphics, int, int)}
|
* Animation works only if the component passed to {@link #paintIcon(Component, Graphics, int, int)}
|
||||||
* is a instance of {@link JComponent}.
|
* is an instance of {@link JComponent}.
|
||||||
* A client property is set on the component to store the animation state.
|
* A client property is set on the component to store the animation state.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -68,7 +68,7 @@ public interface AnimatedIcon
|
|||||||
extends Icon
|
extends Icon
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public default void paintIcon( Component c, Graphics g, int x, int y ) {
|
default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
AnimationSupport.paintIcon( this, c, g, x, y );
|
AnimationSupport.paintIcon( this, c, g, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ public class ColorFunctions
|
|||||||
return color1;
|
return color1;
|
||||||
if( weight <= 0 )
|
if( weight <= 0 )
|
||||||
return color2;
|
return color2;
|
||||||
|
if( color1.equals( color2 ) )
|
||||||
|
return color1;
|
||||||
|
|
||||||
int r1 = color1.getRed();
|
int r1 = color1.getRed();
|
||||||
int g1 = color1.getGreen();
|
int g1 = color1.getGreen();
|
||||||
@@ -196,6 +198,9 @@ public class ColorFunctions
|
|||||||
: (float) Math.pow( (value + 0.055) / 1.055, 2.4 );
|
: (float) Math.pow( (value + 0.055) / 1.055, 2.4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given color functions to the given color and returns the new color.
|
||||||
|
*/
|
||||||
public static Color applyFunctions( Color color, ColorFunction... functions ) {
|
public static Color applyFunctions( Color color, ColorFunction... functions ) {
|
||||||
// if having only a single function of type Mix, then avoid four unnecessary conversions:
|
// if having only a single function of type Mix, then avoid four unnecessary conversions:
|
||||||
// 1. RGB to HSL in this method
|
// 1. RGB to HSL in this method
|
||||||
@@ -221,6 +226,9 @@ public class ColorFunctions
|
|||||||
return HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
|
return HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clamps the given value between 0 and 100.
|
||||||
|
*/
|
||||||
public static float clamp( float value ) {
|
public static float clamp( float value ) {
|
||||||
return (value < 0)
|
return (value < 0)
|
||||||
? 0
|
? 0
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class DerivedColor
|
|||||||
Color result = ColorFunctions.applyFunctions( baseColor, functions );
|
Color result = ColorFunctions.applyFunctions( baseColor, functions );
|
||||||
|
|
||||||
// if the result is equal to the default color, then the original base color
|
// if the result is equal to the default color, then the original base color
|
||||||
// was passed and we can cache this to avoid color calculations
|
// was passed, and we can cache this to avoid color calculations
|
||||||
if( !hasBaseOfDefaultColor && result.getRGB() == this.getRGB() ) {
|
if( !hasBaseOfDefaultColor && result.getRGB() == this.getRGB() ) {
|
||||||
hasBaseOfDefaultColor = true;
|
hasBaseOfDefaultColor = true;
|
||||||
baseOfDefaultColorRGB = baseColor.getRGB();
|
baseOfDefaultColorRGB = baseColor.getRGB();
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class HSLColor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a HSLColor object using an an array containing the
|
* Create a HSLColor object using an array containing the
|
||||||
* individual HSL values and with a default alpha value of 1.
|
* individual HSL values and with a default alpha value of 1.
|
||||||
*
|
*
|
||||||
* @param hsl array containing HSL values
|
* @param hsl array containing HSL values
|
||||||
@@ -87,7 +87,7 @@ public class HSLColor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a HSLColor object using an an array containing the
|
* Create a HSLColor object using an array containing the
|
||||||
* individual HSL values.
|
* individual HSL values.
|
||||||
*
|
*
|
||||||
* @param hsl array containing HSL values
|
* @param hsl array containing HSL values
|
||||||
@@ -291,7 +291,7 @@ public class HSLColor
|
|||||||
|
|
||||||
// Calculate the Saturation
|
// Calculate the Saturation
|
||||||
|
|
||||||
float s = 0;
|
float s;
|
||||||
|
|
||||||
if (max == min)
|
if (max == min)
|
||||||
s = 0;
|
s = 0;
|
||||||
@@ -386,7 +386,7 @@ public class HSLColor
|
|||||||
s /= 100f;
|
s /= 100f;
|
||||||
l /= 100f;
|
l /= 100f;
|
||||||
|
|
||||||
float q = 0;
|
float q;
|
||||||
|
|
||||||
if (l < 0.5)
|
if (l < 0.5)
|
||||||
q = l * (1 + s);
|
q = l * (1 + s);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
|||||||
public class HiDPIUtils
|
public class HiDPIUtils
|
||||||
{
|
{
|
||||||
public interface Painter {
|
public interface Painter {
|
||||||
public void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
|
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
|
||||||
@@ -114,7 +114,7 @@ public class HiDPIUtils
|
|||||||
* painted too far down on some operating systems.
|
* painted too far down on some operating systems.
|
||||||
* The higher the system scale factor is, the more.
|
* The higher the system scale factor is, the more.
|
||||||
* <p>
|
* <p>
|
||||||
* This methods computes a correction value for the Y position.
|
* This method computes a correction value for the Y position.
|
||||||
*/
|
*/
|
||||||
public static float computeTextYCorrection( Graphics2D g ) {
|
public static float computeTextYCorrection( Graphics2D g ) {
|
||||||
if( !useTextYCorrection() || !SystemInfo.isWindows )
|
if( !useTextYCorrection() || !SystemInfo.isWindows )
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public class JavaCompatibility
|
|||||||
getClippedStringMethod = cls.getMethod( SystemInfo.isJava_9_orLater
|
getClippedStringMethod = cls.getMethod( SystemInfo.isJava_9_orLater
|
||||||
? "getClippedString"
|
? "getClippedString"
|
||||||
: "clipStringIfNecessary",
|
: "clipStringIfNecessary",
|
||||||
new Class[] { JComponent.class, FontMetrics.class, String.class, int.class } );
|
JComponent.class, FontMetrics.class, String.class, int.class );
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
throw new RuntimeException( ex );
|
throw new RuntimeException( ex );
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class MultiResolutionImageSupport
|
|||||||
* <p>
|
* <p>
|
||||||
* The given dimensions array is only used for {@link #getResolutionVariants(Image)}.
|
* The given dimensions array is only used for {@link #getResolutionVariants(Image)}.
|
||||||
* The producer function may be invoked with any dimension (that is not contained in
|
* The producer function may be invoked with any dimension (that is not contained in
|
||||||
* dimensions array) and is expected to produce a image for the passed in dimension.
|
* dimensions array) and is expected to produce an image for the passed in dimension.
|
||||||
*
|
*
|
||||||
* @param baseImageIndex index of the base image in the dimensions array
|
* @param baseImageIndex index of the base image in the dimensions array
|
||||||
* @param dimensions dimensions of resolution variants (sorted by size; smallest first)
|
* @param dimensions dimensions of resolution variants (sorted by size; smallest first)
|
||||||
@@ -92,7 +92,7 @@ public class MultiResolutionImageSupport
|
|||||||
* for "disabled" state.
|
* for "disabled" state.
|
||||||
*
|
*
|
||||||
* @param image a multi-resolution image that is mapped using the given mapper function
|
* @param image a multi-resolution image that is mapped using the given mapper function
|
||||||
* @param mapper mapper function that maps a single resolution variant to a new image (e.g. applying an filter)
|
* @param mapper mapper function that maps a single resolution variant to a new image (e.g. applying a filter)
|
||||||
* @return a multi-resolution image on Java 9 or later; a mapped image on Java 8
|
* @return a multi-resolution image on Java 9 or later; a mapped image on Java 8
|
||||||
*/
|
*/
|
||||||
public static Image map( Image image, Function<Image, Image> mapper ) {
|
public static Image map( Image image, Function<Image, Image> mapper ) {
|
||||||
@@ -104,7 +104,7 @@ public class MultiResolutionImageSupport
|
|||||||
* <p>
|
* <p>
|
||||||
* If the given image is a multi-resolution image then invokes
|
* If the given image is a multi-resolution image then invokes
|
||||||
* {@code java.awt.image.MultiResolutionImage.getResolutionVariant(destImageWidth, destImageHeight)}.
|
* {@code java.awt.image.MultiResolutionImage.getResolutionVariant(destImageWidth, destImageHeight)}.
|
||||||
* Otherwise returns the given image.
|
* Otherwise, returns the given image.
|
||||||
*/
|
*/
|
||||||
public static Image getResolutionVariant( Image image, int destImageWidth, int destImageHeight ) {
|
public static Image getResolutionVariant( Image image, int destImageWidth, int destImageHeight ) {
|
||||||
return image;
|
return image;
|
||||||
@@ -115,7 +115,7 @@ public class MultiResolutionImageSupport
|
|||||||
* <p>
|
* <p>
|
||||||
* If the given image is a multi-resolution image then invokes
|
* If the given image is a multi-resolution image then invokes
|
||||||
* {@code java.awt.image.MultiResolutionImage.getResolutionVariants()}.
|
* {@code java.awt.image.MultiResolutionImage.getResolutionVariants()}.
|
||||||
* Otherwise returns a list containing only the given image.
|
* Otherwise, returns a list containing only the given image.
|
||||||
*/
|
*/
|
||||||
public static List<Image> getResolutionVariants( Image image ) {
|
public static List<Image> getResolutionVariants( Image image ) {
|
||||||
return Collections.singletonList( image );
|
return Collections.singletonList( image );
|
||||||
|
|||||||
@@ -60,6 +60,19 @@ public class NativeLibrary
|
|||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load native library from given file.
|
||||||
|
*
|
||||||
|
* @param libraryFile the file of the native library
|
||||||
|
* @param supported whether the native library is supported on the current platform
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public NativeLibrary( File libraryFile, boolean supported ) {
|
||||||
|
this.loaded = supported
|
||||||
|
? loadLibraryFromFile( libraryFile )
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the native library is loaded.
|
* Returns whether the native library is loaded.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -120,16 +133,29 @@ public class NativeLibrary
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean loadLibraryFromFile( File libraryFile ) {
|
||||||
|
try {
|
||||||
|
System.load( libraryFile.getAbsolutePath() );
|
||||||
|
return true;
|
||||||
|
} catch( Throwable ex ) {
|
||||||
|
log( null, ex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add prefix and suffix to library name.
|
||||||
|
* <ul>
|
||||||
|
* <li>Windows: libraryName + ".dll"
|
||||||
|
* <li>macOS: "lib" + libraryName + ".dylib"
|
||||||
|
* <li>Linux: "lib" + libraryName + ".so"
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
private static String decorateLibraryName( String libraryName ) {
|
private static String decorateLibraryName( String libraryName ) {
|
||||||
if( SystemInfo.isWindows )
|
|
||||||
return libraryName.concat( ".dll" );
|
|
||||||
|
|
||||||
String suffix = SystemInfo.isMacOS ? ".dylib" : ".so";
|
|
||||||
|
|
||||||
int sep = libraryName.lastIndexOf( '/' );
|
int sep = libraryName.lastIndexOf( '/' );
|
||||||
return (sep >= 0)
|
return (sep >= 0)
|
||||||
? libraryName.substring( 0, sep + 1 ) + "lib" + libraryName.substring( sep + 1 ) + suffix
|
? libraryName.substring( 0, sep + 1 ) + System.mapLibraryName( libraryName.substring( sep + 1 ) )
|
||||||
: "lib" + libraryName + suffix;
|
: System.mapLibraryName( libraryName );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void log( String msg, Throwable thrown ) {
|
private static void log( String msg, Throwable thrown ) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.util;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for Swing.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public class SwingUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Search for a (grand) child component with the given name.
|
||||||
|
*
|
||||||
|
* @return a component; or {@code null}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
public static <T extends Component> T getComponentByName( Container parent, String name ) {
|
||||||
|
for( Component child : parent.getComponents() ) {
|
||||||
|
if( name.equals( child.getName() ) )
|
||||||
|
return (T) child;
|
||||||
|
|
||||||
|
if( child instanceof Container ) {
|
||||||
|
T c = getComponentByName( (Container) child, name );
|
||||||
|
if( c != null )
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,9 @@ 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).
|
||||||
|
* (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;
|
||||||
@@ -47,8 +50,10 @@ public class SystemInfo
|
|||||||
public static final long javaVersion;
|
public static final long javaVersion;
|
||||||
public static final boolean isJava_9_orLater;
|
public static final boolean isJava_9_orLater;
|
||||||
public static final boolean isJava_11_orLater;
|
public static final boolean isJava_11_orLater;
|
||||||
|
/** @since 2.3 */ public static final boolean isJava_12_orLater;
|
||||||
public static final boolean isJava_15_orLater;
|
public static final boolean isJava_15_orLater;
|
||||||
/** @since 2 */ public static final boolean isJava_17_orLater;
|
/** @since 2 */ public static final boolean isJava_17_orLater;
|
||||||
|
/** @since 2 */ public static final boolean isJava_18_orLater;
|
||||||
|
|
||||||
// Java VMs
|
// Java VMs
|
||||||
public static final boolean isJetBrainsJVM;
|
public static final boolean isJetBrainsJVM;
|
||||||
@@ -62,6 +67,9 @@ public class SystemInfo
|
|||||||
/** @since 1.1.2 */ public static final boolean isWebswing;
|
/** @since 1.1.2 */ public static final boolean isWebswing;
|
||||||
/** @since 1.1.1 */ public static final boolean isWinPE;
|
/** @since 1.1.1 */ public static final boolean isWinPE;
|
||||||
|
|
||||||
|
// features
|
||||||
|
/** @since 2.3 */ public static final boolean isMacFullWindowContentSupported;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// platforms
|
// platforms
|
||||||
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
|
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
|
||||||
@@ -72,6 +80,8 @@ 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 ));
|
||||||
@@ -86,8 +96,10 @@ public class SystemInfo
|
|||||||
javaVersion = scanVersion( System.getProperty( "java.version" ) );
|
javaVersion = scanVersion( System.getProperty( "java.version" ) );
|
||||||
isJava_9_orLater = (javaVersion >= toVersion( 9, 0, 0, 0 ));
|
isJava_9_orLater = (javaVersion >= toVersion( 9, 0, 0, 0 ));
|
||||||
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
|
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
|
||||||
|
isJava_12_orLater = (javaVersion >= toVersion( 12, 0, 0, 0 ));
|
||||||
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
|
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
|
||||||
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
|
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
|
||||||
|
isJava_18_orLater = (javaVersion >= toVersion( 18, 0, 0, 0 ));
|
||||||
|
|
||||||
// Java VMs
|
// Java VMs
|
||||||
isJetBrainsJVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
isJetBrainsJVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
||||||
@@ -101,6 +113,12 @@ public class SystemInfo
|
|||||||
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
|
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
|
||||||
isWebswing = (System.getProperty( "webswing.rootDir" ) != null);
|
isWebswing = (System.getProperty( "webswing.rootDir" ) != null);
|
||||||
isWinPE = isWindows && "X:\\Windows\\System32".equalsIgnoreCase( System.getProperty( "user.dir" ) );
|
isWinPE = isWindows && "X:\\Windows\\System32".equalsIgnoreCase( System.getProperty( "user.dir" ) );
|
||||||
|
|
||||||
|
// features
|
||||||
|
// available since Java 12; backported to Java 11.0.8 and 8u292
|
||||||
|
isMacFullWindowContentSupported =
|
||||||
|
javaVersion >= toVersion( 11, 0, 8, 0 ) ||
|
||||||
|
(javaVersion >= toVersion( 1, 8, 0, 292 ) && !isJava_9_orLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long scanVersion( String version ) {
|
public static long scanVersion( String version ) {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class UIScale
|
|||||||
// Java 9 and later supports per-monitor scaling
|
// Java 9 and later supports per-monitor scaling
|
||||||
jreHiDPI = true;
|
jreHiDPI = true;
|
||||||
} else if( SystemInfo.isJetBrainsJVM ) {
|
} else if( SystemInfo.isJetBrainsJVM ) {
|
||||||
// IntelliJ IDEA ships its own JetBrains Java 8 JRE that may supports per-monitor scaling
|
// IntelliJ IDEA ships its own JetBrains Java 8 JRE that may support per-monitor scaling
|
||||||
// see com.intellij.ui.JreHiDpiUtil.isJreHiDPIEnabled()
|
// see com.intellij.ui.JreHiDpiUtil.isJreHiDPIEnabled()
|
||||||
try {
|
try {
|
||||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||||
@@ -411,7 +411,7 @@ public class UIScale
|
|||||||
* Scales the given dimension with the user scale factor.
|
* Scales the given dimension with the user scale factor.
|
||||||
* <p>
|
* <p>
|
||||||
* If user scale factor is 1, then the given dimension is simply returned.
|
* If user scale factor is 1, then the given dimension is simply returned.
|
||||||
* Otherwise a new instance of {@link Dimension} or {@link DimensionUIResource}
|
* Otherwise, a new instance of {@link Dimension} or {@link DimensionUIResource}
|
||||||
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
||||||
*/
|
*/
|
||||||
public static Dimension scale( Dimension dimension ) {
|
public static Dimension scale( Dimension dimension ) {
|
||||||
@@ -427,7 +427,7 @@ public class UIScale
|
|||||||
* Scales the given insets with the user scale factor.
|
* Scales the given insets with the user scale factor.
|
||||||
* <p>
|
* <p>
|
||||||
* If user scale factor is 1, then the given insets is simply returned.
|
* If user scale factor is 1, then the given insets is simply returned.
|
||||||
* Otherwise a new instance of {@link Insets} or {@link InsetsUIResource}
|
* Otherwise, a new instance of {@link Insets} or {@link InsetsUIResource}
|
||||||
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
||||||
*/
|
*/
|
||||||
public static Insets scale( Insets insets ) {
|
public static Insets scale( Insets insets ) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||||
# Instead copy and modify only those properties that you need to alter.
|
# Instead, copy and modify only those properties that you need to alter.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||||
# Instead copy and modify only those properties that you need to alter.
|
# Instead, copy and modify only those properties that you need to alter.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
||||||
@@ -240,6 +240,7 @@ MenuBar.borderColor = $Separator.foreground
|
|||||||
#---- PasswordField ----
|
#---- PasswordField ----
|
||||||
|
|
||||||
PasswordField.capsLockIconColor = #ffffff64
|
PasswordField.capsLockIconColor = #ffffff64
|
||||||
|
PasswordField.revealIconColor = @foreground
|
||||||
|
|
||||||
|
|
||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
@@ -251,6 +252,7 @@ Popup.dropShadowOpacity = 0.25
|
|||||||
#---- PopupMenu ----
|
#---- PopupMenu ----
|
||||||
|
|
||||||
PopupMenu.borderColor = tint(@background,17%)
|
PopupMenu.borderColor = tint(@background,17%)
|
||||||
|
PopupMenu.hoverScrollArrowBackground = lighten(@background,5%)
|
||||||
|
|
||||||
|
|
||||||
#---- ProgressBar ----
|
#---- ProgressBar ----
|
||||||
@@ -289,7 +291,7 @@ Slider.trackValueColor = @accentSliderColor
|
|||||||
Slider.trackColor = lighten(@background,15%)
|
Slider.trackColor = lighten(@background,15%)
|
||||||
Slider.thumbColor = $Slider.trackValueColor
|
Slider.thumbColor = $Slider.trackValueColor
|
||||||
Slider.tickColor = @disabledForeground
|
Slider.tickColor = @disabledForeground
|
||||||
Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
Slider.focusedColor = fade(changeLightness($Component.focusColor,60%,derived),30%,derived)
|
||||||
Slider.hoverThumbColor = lighten($Slider.thumbColor,5%,derived)
|
Slider.hoverThumbColor = lighten($Slider.thumbColor,5%,derived)
|
||||||
Slider.pressedThumbColor = lighten($Slider.thumbColor,8%,derived)
|
Slider.pressedThumbColor = lighten($Slider.thumbColor,8%,derived)
|
||||||
Slider.disabledTrackColor = lighten(@background,10%)
|
Slider.disabledTrackColor = lighten(@background,10%)
|
||||||
@@ -304,6 +306,7 @@ SplitPaneDivider.draggingColor = $Component.borderColor
|
|||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.underlineColor = @accentUnderlineColor
|
TabbedPane.underlineColor = @accentUnderlineColor
|
||||||
|
TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,60%)
|
||||||
TabbedPane.disabledUnderlineColor = lighten(@background,23%)
|
TabbedPane.disabledUnderlineColor = lighten(@background,23%)
|
||||||
TabbedPane.hoverColor = darken($TabbedPane.background,5%,derived noAutoInverse)
|
TabbedPane.hoverColor = darken($TabbedPane.background,5%,derived noAutoInverse)
|
||||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,25%)
|
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,25%)
|
||||||
@@ -322,7 +325,7 @@ TabbedPane.closePressedForeground = $TabbedPane.closeHoverForeground
|
|||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
Table.gridColor = lighten($Table.background,5%)
|
Table.gridColor = lighten($Table.background,8%)
|
||||||
|
|
||||||
|
|
||||||
#---- TableHeader ----
|
#---- TableHeader ----
|
||||||
@@ -334,8 +337,8 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
|||||||
#---- TitlePane ----
|
#---- TitlePane ----
|
||||||
|
|
||||||
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
||||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
TitlePane.buttonHoverBackground = lighten($TitlePane.background,15%,derived)
|
||||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,20%,derived)
|
TitlePane.buttonPressedBackground = lighten($TitlePane.background,10%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
@@ -367,7 +370,6 @@ Tree.hash = lighten($Tree.background,5%)
|
|||||||
focusable: false; \
|
focusable: false; \
|
||||||
toolbar.margin: 1,1,1,1; \
|
toolbar.margin: 1,1,1,1; \
|
||||||
toolbar.spacingInsets: 1,1,1,1; \
|
toolbar.spacingInsets: 1,1,1,1; \
|
||||||
background: $TextField.background; \
|
toolbar.hoverBackground: lighten($TextField.background,5%); \
|
||||||
toolbar.hoverBackground: lighten($TextField.background,4%,derived); \
|
toolbar.pressedBackground: lighten($TextField.background,10%); \
|
||||||
toolbar.pressedBackground: lighten($TextField.background,6%,derived); \
|
toolbar.selectedBackground: lighten($TextField.background,15%)
|
||||||
toolbar.selectedBackground: lighten($TextField.background,12%,derived)
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||||
# Instead copy and modify only those properties that you need to alter.
|
# Instead, copy and modify only those properties that you need to alter.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||||
# Instead copy and modify only those properties that you need to alter.
|
# Instead, copy and modify only those properties that you need to alter.
|
||||||
#
|
#
|
||||||
|
|
||||||
#---- typography / fonts ----
|
#---- typography / fonts ----
|
||||||
@@ -332,6 +332,7 @@ FileView.fileIcon = com.formdev.flatlaf.icons.FlatFileViewFileIcon
|
|||||||
FileView.computerIcon = com.formdev.flatlaf.icons.FlatFileViewComputerIcon
|
FileView.computerIcon = com.formdev.flatlaf.icons.FlatFileViewComputerIcon
|
||||||
FileView.hardDriveIcon = com.formdev.flatlaf.icons.FlatFileViewHardDriveIcon
|
FileView.hardDriveIcon = com.formdev.flatlaf.icons.FlatFileViewHardDriveIcon
|
||||||
FileView.floppyDriveIcon = com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon
|
FileView.floppyDriveIcon = com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon
|
||||||
|
FileView.fullRowSelection = true
|
||||||
|
|
||||||
|
|
||||||
#---- FormattedTextField ----
|
#---- FormattedTextField ----
|
||||||
@@ -487,7 +488,6 @@ PasswordField.showCapsLock = true
|
|||||||
PasswordField.showRevealButton = false
|
PasswordField.showRevealButton = false
|
||||||
PasswordField.capsLockIcon = com.formdev.flatlaf.icons.FlatCapsLockIcon
|
PasswordField.capsLockIcon = com.formdev.flatlaf.icons.FlatCapsLockIcon
|
||||||
PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
||||||
PasswordField.revealIconColor = lazy(Actions.Grey)
|
|
||||||
|
|
||||||
|
|
||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
@@ -501,6 +501,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.background = @menuBackground
|
PopupMenu.background = @menuBackground
|
||||||
|
PopupMenu.scrollArrowColor = @buttonArrowColor
|
||||||
|
|
||||||
|
|
||||||
#---- PopupMenuSeparator ----
|
#---- PopupMenuSeparator ----
|
||||||
@@ -555,6 +556,7 @@ RootPane.honorDialogMinimumSizeOnResize = true
|
|||||||
#---- ScrollBar ----
|
#---- ScrollBar ----
|
||||||
|
|
||||||
ScrollBar.width = 10
|
ScrollBar.width = 10
|
||||||
|
ScrollBar.minimumButtonSize = 12,12
|
||||||
ScrollBar.minimumThumbSize = 10,10
|
ScrollBar.minimumThumbSize = 10,10
|
||||||
ScrollBar.maximumThumbSize = 100000,100000
|
ScrollBar.maximumThumbSize = 100000,100000
|
||||||
ScrollBar.trackInsets = 0,0,0,0
|
ScrollBar.trackInsets = 0,0,0,0
|
||||||
@@ -589,13 +591,13 @@ ScrollPane.smoothScrolling = true
|
|||||||
|
|
||||||
#---- SearchField ----
|
#---- SearchField ----
|
||||||
|
|
||||||
SearchField.searchIconColor = fadeout(Actions.GreyInline,10%,lazy)
|
SearchField.searchIconColor = fade(Actions.GreyInline,90%,lazy)
|
||||||
SearchField.searchIconHoverColor = fadeout(Actions.GreyInline,30%,lazy)
|
SearchField.searchIconHoverColor = fade(Actions.GreyInline,70%,lazy)
|
||||||
SearchField.searchIconPressedColor = fadeout(Actions.GreyInline,50%,lazy)
|
SearchField.searchIconPressedColor = fade(Actions.GreyInline,50%,lazy)
|
||||||
|
|
||||||
SearchField.clearIconColor = fadeout(Actions.GreyInline,50%,lazy)
|
SearchField.clearIconColor = fade(Actions.GreyInline,50%,lazy)
|
||||||
SearchField.clearIconHoverColor = $SearchField.clearIconColor
|
SearchField.clearIconHoverColor = $SearchField.clearIconColor
|
||||||
SearchField.clearIconPressedColor = fadeout(Actions.GreyInline,20%,lazy)
|
SearchField.clearIconPressedColor = fade(Actions.GreyInline,80%,lazy)
|
||||||
|
|
||||||
|
|
||||||
#---- Separator ----
|
#---- Separator ----
|
||||||
@@ -802,8 +804,8 @@ TitlePane.inactiveBackground = $TitlePane.background
|
|||||||
TitlePane.foreground = @foreground
|
TitlePane.foreground = @foreground
|
||||||
TitlePane.inactiveForeground = @disabledForeground
|
TitlePane.inactiveForeground = @disabledForeground
|
||||||
|
|
||||||
TitlePane.closeHoverBackground = #e81123
|
TitlePane.closeHoverBackground = #c42b1c
|
||||||
TitlePane.closePressedBackground = fade($TitlePane.closeHoverBackground,60%)
|
TitlePane.closePressedBackground = fade($TitlePane.closeHoverBackground,90%)
|
||||||
TitlePane.closeHoverForeground = #fff
|
TitlePane.closeHoverForeground = #fff
|
||||||
TitlePane.closePressedForeground = #fff
|
TitlePane.closePressedForeground = #fff
|
||||||
|
|
||||||
@@ -827,6 +829,7 @@ ToggleButton.tab.underlineHeight = 2
|
|||||||
ToggleButton.tab.underlineColor = $TabbedPane.underlineColor
|
ToggleButton.tab.underlineColor = $TabbedPane.underlineColor
|
||||||
ToggleButton.tab.disabledUnderlineColor = $TabbedPane.disabledUnderlineColor
|
ToggleButton.tab.disabledUnderlineColor = $TabbedPane.disabledUnderlineColor
|
||||||
ToggleButton.tab.selectedBackground = $?TabbedPane.selectedBackground
|
ToggleButton.tab.selectedBackground = $?TabbedPane.selectedBackground
|
||||||
|
ToggleButton.tab.selectedForeground = $?TabbedPane.selectedForeground
|
||||||
ToggleButton.tab.hoverBackground = $TabbedPane.hoverColor
|
ToggleButton.tab.hoverBackground = $TabbedPane.hoverColor
|
||||||
ToggleButton.tab.focusBackground = $TabbedPane.focusColor
|
ToggleButton.tab.focusBackground = $TabbedPane.focusColor
|
||||||
|
|
||||||
@@ -920,6 +923,5 @@ Tree.icon.openColor = @icon
|
|||||||
focusable: false; \
|
focusable: false; \
|
||||||
toolbar.margin: 1,1,1,1; \
|
toolbar.margin: 1,1,1,1; \
|
||||||
toolbar.spacingInsets: 1,1,1,1; \
|
toolbar.spacingInsets: 1,1,1,1; \
|
||||||
background: $TextField.background; \
|
toolbar.hoverBackground: null; \
|
||||||
toolbar.hoverBackground: $TextField.background; \
|
toolbar.pressedBackground: null
|
||||||
toolbar.pressedBackground: $TextField.background
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#
|
#
|
||||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||||
# Instead copy and modify only those properties that you need to alter.
|
# Instead, copy and modify only those properties that you need to alter.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
||||||
@@ -247,6 +247,7 @@ MenuBar.borderColor = $Separator.foreground
|
|||||||
#---- PasswordField ----
|
#---- PasswordField ----
|
||||||
|
|
||||||
PasswordField.capsLockIconColor = #00000064
|
PasswordField.capsLockIconColor = #00000064
|
||||||
|
PasswordField.revealIconColor = tint(@foreground,40%)
|
||||||
|
|
||||||
|
|
||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
@@ -258,6 +259,7 @@ Popup.dropShadowOpacity = 0.15
|
|||||||
#---- PopupMenu ----
|
#---- PopupMenu ----
|
||||||
|
|
||||||
PopupMenu.borderColor = shade(@background,28%)
|
PopupMenu.borderColor = shade(@background,28%)
|
||||||
|
PopupMenu.hoverScrollArrowBackground = darken(@background,5%)
|
||||||
|
|
||||||
|
|
||||||
#---- ProgressBar ----
|
#---- ProgressBar ----
|
||||||
@@ -296,7 +298,7 @@ Slider.trackValueColor = @accentSliderColor
|
|||||||
Slider.trackColor = darken(@background,18%)
|
Slider.trackColor = darken(@background,18%)
|
||||||
Slider.thumbColor = $Slider.trackValueColor
|
Slider.thumbColor = $Slider.trackValueColor
|
||||||
Slider.tickColor = @disabledForeground
|
Slider.tickColor = @disabledForeground
|
||||||
Slider.focusedColor = fade($Component.focusColor,50%,derived)
|
Slider.focusedColor = fade(changeLightness($Component.focusColor,75%,derived),50%,derived)
|
||||||
Slider.hoverThumbColor = darken($Slider.thumbColor,5%,derived)
|
Slider.hoverThumbColor = darken($Slider.thumbColor,5%,derived)
|
||||||
Slider.pressedThumbColor = darken($Slider.thumbColor,8%,derived)
|
Slider.pressedThumbColor = darken($Slider.thumbColor,8%,derived)
|
||||||
Slider.disabledTrackColor = darken(@background,13%)
|
Slider.disabledTrackColor = darken(@background,13%)
|
||||||
@@ -311,6 +313,7 @@ SplitPaneDivider.draggingColor = $Component.borderColor
|
|||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.underlineColor = @accentUnderlineColor
|
TabbedPane.underlineColor = @accentUnderlineColor
|
||||||
|
TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,50%)
|
||||||
TabbedPane.disabledUnderlineColor = darken(@background,28%)
|
TabbedPane.disabledUnderlineColor = darken(@background,28%)
|
||||||
TabbedPane.hoverColor = darken($TabbedPane.background,7%,derived)
|
TabbedPane.hoverColor = darken($TabbedPane.background,7%,derived)
|
||||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%)
|
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%)
|
||||||
@@ -329,7 +332,7 @@ TabbedPane.closePressedForeground = $TabbedPane.closeHoverForeground
|
|||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
Table.gridColor = darken($Table.background,5%)
|
Table.gridColor = darken($Table.background,8%)
|
||||||
|
|
||||||
|
|
||||||
#---- TableHeader ----
|
#---- TableHeader ----
|
||||||
@@ -342,7 +345,7 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
|||||||
|
|
||||||
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
||||||
TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
||||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,20%,derived)
|
TitlePane.buttonPressedBackground = darken($TitlePane.background,8%,derived)
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
@@ -374,7 +377,6 @@ Tree.hash = darken($Tree.background,10%)
|
|||||||
focusable: false; \
|
focusable: false; \
|
||||||
toolbar.margin: 1,1,1,1; \
|
toolbar.margin: 1,1,1,1; \
|
||||||
toolbar.spacingInsets: 1,1,1,1; \
|
toolbar.spacingInsets: 1,1,1,1; \
|
||||||
background: $TextField.background; \
|
toolbar.hoverBackground: darken($TextField.background,4%); \
|
||||||
toolbar.hoverBackground: darken($TextField.background,4%,derived); \
|
toolbar.pressedBackground: darken($TextField.background,8%); \
|
||||||
toolbar.pressedBackground: darken($TextField.background,8%,derived); \
|
toolbar.selectedBackground: darken($TextField.background,12%)
|
||||||
toolbar.selectedBackground: darken($TextField.background,12%,derived)
|
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ Button.default.hoverBorderColor = null
|
|||||||
[dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9
|
[dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9
|
||||||
|
|
||||||
|
|
||||||
|
#---- Component ----
|
||||||
|
|
||||||
|
Component.accentColor = lazy(ProgressBar.foreground)
|
||||||
|
|
||||||
|
|
||||||
#---- HelpButton ----
|
#---- HelpButton ----
|
||||||
|
|
||||||
HelpButton.hoverBorderColor = null
|
HelpButton.hoverBorderColor = null
|
||||||
@@ -77,6 +82,13 @@ HelpButton.hoverBorderColor = null
|
|||||||
Slider.focusedColor = fade($Component.focusColor,40%,derived)
|
Slider.focusedColor = fade($Component.focusColor,40%,derived)
|
||||||
|
|
||||||
|
|
||||||
|
#---- TabbedPane ----
|
||||||
|
|
||||||
|
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
|
||||||
|
[light]TabbedPane.inactiveUnderlineColor = #9ca7b8
|
||||||
|
[dark]TabbedPane.inactiveUnderlineColor = #747a80
|
||||||
|
|
||||||
|
|
||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|
||||||
ToggleButton.startBackground = $ToggleButton.background
|
ToggleButton.startBackground = $ToggleButton.background
|
||||||
@@ -121,6 +133,7 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[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
|
||||||
|
|
||||||
|
[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
|
||||||
@@ -129,37 +142,50 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||||
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||||
|
|
||||||
|
[Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
|
||||||
[Dark_Flat_Theme]TableHeader.background = #3B3B3B
|
[Dark_Flat_Theme]TableHeader.background = #3B3B3B
|
||||||
|
|
||||||
[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]ProgressBar.selectionBackground = #fff
|
[Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
|
||||||
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
||||||
|
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
|
||||||
|
[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_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_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
|
||||||
|
|
||||||
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
||||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
[Hiberbee_Dark]TabbedPane.selectedBackground = #434241
|
||||||
|
[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
|
||||||
|
|
||||||
|
[High_contrast]Component.accentColor = lazy(Component.focusColor)
|
||||||
[High_contrast]ToggleButton.selectedBackground = #fff
|
[High_contrast]ToggleButton.selectedBackground = #fff
|
||||||
[High_contrast]ToggleButton.selectedForeground = #000
|
[High_contrast]ToggleButton.selectedForeground = #000
|
||||||
[High_contrast]ToggleButton.disabledSelectedBackground = #444
|
[High_contrast]ToggleButton.disabledSelectedBackground = #444
|
||||||
[High_contrast]ToggleButton.toolbar.selectedBackground = #fff
|
[High_contrast]ToggleButton.toolbar.selectedBackground = #fff
|
||||||
|
[High_contrast][style]Button.inTextField = \
|
||||||
|
toolbar.hoverBackground: #444; \
|
||||||
|
toolbar.pressedBackground: #666; \
|
||||||
|
toolbar.selectedBackground: #fff
|
||||||
|
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
|
||||||
|
|
||||||
|
[Light_Flat]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Light_Flat]TableHeader.background = #E5E5E9
|
[Light_Flat]TableHeader.background = #E5E5E9
|
||||||
|
|
||||||
[Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
@@ -175,6 +201,8 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
[Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
|
||||||
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
[Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
|
||||||
|
|
||||||
|
[Monokai_Pro]TitledBorder.titleColor = @foreground
|
||||||
|
|
||||||
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
[Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||||
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
|
|
||||||
@@ -182,8 +210,12 @@ ToggleButton.endBackground = $ToggleButton.background
|
|||||||
[One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
[One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||||
[One_Dark]Slider.focusedColor = fade(#568af2,40%)
|
[One_Dark]Slider.focusedColor = fade(#568af2,40%)
|
||||||
|
|
||||||
|
[Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
[Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
|
||||||
|
|
||||||
|
[Solarized_Light---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||||
|
|
||||||
|
[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
|
||||||
[vuesion-theme]Slider.trackValueColor = #ececee
|
[vuesion-theme]Slider.trackValueColor = #ececee
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
#---- 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.collapseLeftToolTipText = Contraer Panel Izquierdo
|
||||||
|
SplitPaneDivider.collapseRightToolTipText = Contraer panel Derecho
|
||||||
|
SplitPaneDivider.collapseTopToolTipText = Contraer panel Superior
|
||||||
|
SplitPaneDivider.collapseBottomToolTipText = Contraer Panel Inferior
|
||||||
|
SplitPaneDivider.expandLeftToolTipText = Expandir Panel Izquierdo
|
||||||
|
SplitPaneDivider.expandRightToolTipText = Expandir Panel Derecho
|
||||||
|
SplitPaneDivider.expandTopToolTipText = Expandir Panel Superior
|
||||||
|
SplitPaneDivider.expandBottomToolTipText = Expandir Panel Inferior
|
||||||
|
|
||||||
|
|
||||||
|
#---- TabbedPane ----
|
||||||
|
|
||||||
|
TabbedPane.moreTabsButtonToolTipText = Mostrar Pesta\u00F1as Ocultas
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.icons;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import javax.swing.Icon;
|
||||||
|
import com.formdev.flatlaf.ui.TestUtils;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
|
||||||
|
class TestFlatIconPaintingNullComponent
|
||||||
|
{
|
||||||
|
static Graphics graphics;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() {
|
||||||
|
TestUtils.setup( false );
|
||||||
|
graphics = new BufferedImage( 32, 32, BufferedImage.TYPE_INT_ARGB ).getGraphics();
|
||||||
|
graphics.setColor( Color.white );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void cleanup() {
|
||||||
|
TestUtils.cleanup();
|
||||||
|
graphics = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void flatHelpButtonIcon() {
|
||||||
|
paintWithoutException( new FlatHelpButtonIcon() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void flatMenuArrowIcon() {
|
||||||
|
paintWithoutException( new FlatMenuArrowIcon() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void flatSearchIcon() {
|
||||||
|
paintWithoutException( new FlatSearchIcon() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void paintWithoutException( Icon icon ) {
|
||||||
|
graphics.clearRect( 0, 0, 32, 32 );
|
||||||
|
assertDoesNotThrow( () -> icon.paintIcon( null, graphics, 0, 0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ public class TestFlatStyleClasses
|
|||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void setup() {
|
static void setup() {
|
||||||
System.setProperty( FlatSystemProperties.UI_SCALE_ENABLED, "false" );
|
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||||
TestUtils.setup( false );
|
TestUtils.setup( false );
|
||||||
|
|
||||||
UIManager.put( "[style]Button.primary", BUTTON_PRIMARY );
|
UIManager.put( "[style]Button.primary", BUTTON_PRIMARY );
|
||||||
@@ -100,7 +100,7 @@ public class TestFlatStyleClasses
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void cleanup() {
|
static void cleanup() {
|
||||||
TestUtils.cleanup();
|
TestUtils.cleanup();
|
||||||
System.clearProperty( FlatSystemProperties.UI_SCALE_ENABLED );
|
System.clearProperty( FlatSystemProperties.UI_SCALE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -96,19 +96,26 @@ public class TestFlatStyleableInfo
|
|||||||
"minimumWidth", int.class,
|
"minimumWidth", int.class,
|
||||||
|
|
||||||
"focusedBackground", Color.class,
|
"focusedBackground", Color.class,
|
||||||
|
"focusedForeground", Color.class,
|
||||||
"hoverBackground", Color.class,
|
"hoverBackground", Color.class,
|
||||||
|
"hoverForeground", Color.class,
|
||||||
"pressedBackground", Color.class,
|
"pressedBackground", Color.class,
|
||||||
|
"pressedForeground", Color.class,
|
||||||
"selectedBackground", Color.class,
|
"selectedBackground", Color.class,
|
||||||
"selectedForeground", Color.class,
|
"selectedForeground", Color.class,
|
||||||
"disabledBackground", Color.class,
|
"disabledBackground", Color.class,
|
||||||
"disabledText", Color.class,
|
"disabledText", Color.class,
|
||||||
"disabledSelectedBackground", Color.class,
|
"disabledSelectedBackground", Color.class,
|
||||||
|
"disabledSelectedForeground", Color.class,
|
||||||
|
|
||||||
"default.background", Color.class,
|
"default.background", Color.class,
|
||||||
"default.foreground", Color.class,
|
"default.foreground", Color.class,
|
||||||
"default.focusedBackground", Color.class,
|
"default.focusedBackground", Color.class,
|
||||||
|
"default.focusedForeground", Color.class,
|
||||||
"default.hoverBackground", Color.class,
|
"default.hoverBackground", Color.class,
|
||||||
|
"default.hoverForeground", Color.class,
|
||||||
"default.pressedBackground", Color.class,
|
"default.pressedBackground", Color.class,
|
||||||
|
"default.pressedForeground", Color.class,
|
||||||
"default.boldText", boolean.class,
|
"default.boldText", boolean.class,
|
||||||
|
|
||||||
"paintShadow", boolean.class,
|
"paintShadow", boolean.class,
|
||||||
@@ -118,8 +125,13 @@ public class TestFlatStyleableInfo
|
|||||||
|
|
||||||
"toolbar.spacingInsets", Insets.class,
|
"toolbar.spacingInsets", Insets.class,
|
||||||
"toolbar.hoverBackground", Color.class,
|
"toolbar.hoverBackground", Color.class,
|
||||||
|
"toolbar.hoverForeground", Color.class,
|
||||||
"toolbar.pressedBackground", Color.class,
|
"toolbar.pressedBackground", Color.class,
|
||||||
|
"toolbar.pressedForeground", Color.class,
|
||||||
"toolbar.selectedBackground", Color.class,
|
"toolbar.selectedBackground", Color.class,
|
||||||
|
"toolbar.selectedForeground", Color.class,
|
||||||
|
"toolbar.disabledSelectedBackground", Color.class,
|
||||||
|
"toolbar.disabledSelectedForeground", Color.class,
|
||||||
|
|
||||||
"buttonType", String.class,
|
"buttonType", String.class,
|
||||||
"squareSize", boolean.class,
|
"squareSize", boolean.class,
|
||||||
@@ -422,6 +434,10 @@ public class TestFlatStyleableInfo
|
|||||||
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
|
"arrowType", String.class,
|
||||||
|
"scrollArrowColor", Color.class,
|
||||||
|
"hoverScrollArrowBackground", Color.class,
|
||||||
|
|
||||||
"borderInsets", Insets.class,
|
"borderInsets", Insets.class,
|
||||||
"borderColor", Color.class
|
"borderColor", Color.class
|
||||||
);
|
);
|
||||||
@@ -539,6 +555,7 @@ public class TestFlatStyleableInfo
|
|||||||
"maximumThumbSize", Dimension.class,
|
"maximumThumbSize", Dimension.class,
|
||||||
"allowsAbsolutePositioning", boolean.class,
|
"allowsAbsolutePositioning", boolean.class,
|
||||||
|
|
||||||
|
"minimumButtonSize", Dimension.class,
|
||||||
"trackInsets", Insets.class,
|
"trackInsets", Insets.class,
|
||||||
"thumbInsets", Insets.class,
|
"thumbInsets", Insets.class,
|
||||||
"trackArc", int.class,
|
"trackArc", int.class,
|
||||||
@@ -688,6 +705,7 @@ public class TestFlatStyleableInfo
|
|||||||
"selectedBackground", Color.class,
|
"selectedBackground", Color.class,
|
||||||
"selectedForeground", Color.class,
|
"selectedForeground", Color.class,
|
||||||
"underlineColor", Color.class,
|
"underlineColor", Color.class,
|
||||||
|
"inactiveUnderlineColor", Color.class,
|
||||||
"disabledUnderlineColor", Color.class,
|
"disabledUnderlineColor", Color.class,
|
||||||
"hoverColor", Color.class,
|
"hoverColor", Color.class,
|
||||||
"focusColor", Color.class,
|
"focusColor", Color.class,
|
||||||
@@ -857,8 +875,11 @@ public class TestFlatStyleableInfo
|
|||||||
"tab.underlineColor", Color.class,
|
"tab.underlineColor", Color.class,
|
||||||
"tab.disabledUnderlineColor", Color.class,
|
"tab.disabledUnderlineColor", Color.class,
|
||||||
"tab.selectedBackground", Color.class,
|
"tab.selectedBackground", Color.class,
|
||||||
|
"tab.selectedForeground", Color.class,
|
||||||
"tab.hoverBackground", Color.class,
|
"tab.hoverBackground", Color.class,
|
||||||
"tab.focusBackground", Color.class
|
"tab.hoverForeground", Color.class,
|
||||||
|
"tab.focusBackground", Color.class,
|
||||||
|
"tab.focusForeground", Color.class
|
||||||
);
|
);
|
||||||
|
|
||||||
// FlatToggleButtonUI extends FlatButtonUI
|
// FlatToggleButtonUI extends FlatButtonUI
|
||||||
|
|||||||
@@ -221,19 +221,26 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( b, "minimumWidth: 100" );
|
ui.applyStyle( b, "minimumWidth: 100" );
|
||||||
|
|
||||||
ui.applyStyle( b, "focusedBackground: #fff" );
|
ui.applyStyle( b, "focusedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "focusedForeground: #fff" );
|
||||||
ui.applyStyle( b, "hoverBackground: #fff" );
|
ui.applyStyle( b, "hoverBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "hoverForeground: #fff" );
|
||||||
ui.applyStyle( b, "pressedBackground: #fff" );
|
ui.applyStyle( b, "pressedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "pressedForeground: #fff" );
|
||||||
ui.applyStyle( b, "selectedBackground: #fff" );
|
ui.applyStyle( b, "selectedBackground: #fff" );
|
||||||
ui.applyStyle( b, "selectedForeground: #fff" );
|
ui.applyStyle( b, "selectedForeground: #fff" );
|
||||||
ui.applyStyle( b, "disabledBackground: #fff" );
|
ui.applyStyle( b, "disabledBackground: #fff" );
|
||||||
ui.applyStyle( b, "disabledText: #fff" );
|
ui.applyStyle( b, "disabledText: #fff" );
|
||||||
ui.applyStyle( b, "disabledSelectedBackground: #fff" );
|
ui.applyStyle( b, "disabledSelectedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "disabledSelectedForeground: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( b, "default.background: #fff" );
|
ui.applyStyle( b, "default.background: #fff" );
|
||||||
ui.applyStyle( b, "default.foreground: #fff" );
|
ui.applyStyle( b, "default.foreground: #fff" );
|
||||||
ui.applyStyle( b, "default.focusedBackground: #fff" );
|
ui.applyStyle( b, "default.focusedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "default.focusedForeground: #fff" );
|
||||||
ui.applyStyle( b, "default.hoverBackground: #fff" );
|
ui.applyStyle( b, "default.hoverBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "default.hoverForeground: #fff" );
|
||||||
ui.applyStyle( b, "default.pressedBackground: #fff" );
|
ui.applyStyle( b, "default.pressedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "default.pressedForeground: #fff" );
|
||||||
ui.applyStyle( b, "default.boldText: true" );
|
ui.applyStyle( b, "default.boldText: true" );
|
||||||
|
|
||||||
ui.applyStyle( b, "paintShadow: true" );
|
ui.applyStyle( b, "paintShadow: true" );
|
||||||
@@ -243,8 +250,13 @@ public class TestFlatStyling
|
|||||||
|
|
||||||
ui.applyStyle( b, "toolbar.spacingInsets: 1,2,3,4" );
|
ui.applyStyle( b, "toolbar.spacingInsets: 1,2,3,4" );
|
||||||
ui.applyStyle( b, "toolbar.hoverBackground: #fff" );
|
ui.applyStyle( b, "toolbar.hoverBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "toolbar.hoverForeground: #fff" );
|
||||||
ui.applyStyle( b, "toolbar.pressedBackground: #fff" );
|
ui.applyStyle( b, "toolbar.pressedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "toolbar.pressedForeground: #fff" );
|
||||||
ui.applyStyle( b, "toolbar.selectedBackground: #fff" );
|
ui.applyStyle( b, "toolbar.selectedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "toolbar.selectedForeground: #fff" );
|
||||||
|
ui.applyStyle( b, "toolbar.disabledSelectedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "toolbar.disabledSelectedForeground: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( b, "buttonType: help" );
|
ui.applyStyle( b, "buttonType: help" );
|
||||||
ui.applyStyle( b, "squareSize: true" );
|
ui.applyStyle( b, "squareSize: true" );
|
||||||
@@ -565,6 +577,10 @@ public class TestFlatStyling
|
|||||||
JPopupMenu c = new JPopupMenu();
|
JPopupMenu c = new JPopupMenu();
|
||||||
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
||||||
|
|
||||||
|
ui.applyStyle( "arrowType: chevron" );
|
||||||
|
ui.applyStyle( "scrollArrowColor: #fff" );
|
||||||
|
ui.applyStyle( "hoverScrollArrowBackground: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( "borderInsets: 1,2,3,4" );
|
ui.applyStyle( "borderInsets: 1,2,3,4" );
|
||||||
ui.applyStyle( "borderColor: #fff" );
|
ui.applyStyle( "borderColor: #fff" );
|
||||||
|
|
||||||
@@ -684,6 +700,7 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "maximumThumbSize: 1,2" );
|
ui.applyStyle( "maximumThumbSize: 1,2" );
|
||||||
ui.applyStyle( "allowsAbsolutePositioning: true" );
|
ui.applyStyle( "allowsAbsolutePositioning: true" );
|
||||||
|
|
||||||
|
ui.applyStyle( "minimumButtonSize: 1,2" );
|
||||||
ui.applyStyle( "trackInsets: 1,2,3,4" );
|
ui.applyStyle( "trackInsets: 1,2,3,4" );
|
||||||
ui.applyStyle( "thumbInsets: 1,2,3,4" );
|
ui.applyStyle( "thumbInsets: 1,2,3,4" );
|
||||||
ui.applyStyle( "trackArc: 5" );
|
ui.applyStyle( "trackArc: 5" );
|
||||||
@@ -857,6 +874,7 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "selectedBackground: #fff" );
|
ui.applyStyle( "selectedBackground: #fff" );
|
||||||
ui.applyStyle( "selectedForeground: #fff" );
|
ui.applyStyle( "selectedForeground: #fff" );
|
||||||
ui.applyStyle( "underlineColor: #fff" );
|
ui.applyStyle( "underlineColor: #fff" );
|
||||||
|
ui.applyStyle( "inactiveUnderlineColor: #fff" );
|
||||||
ui.applyStyle( "disabledUnderlineColor: #fff" );
|
ui.applyStyle( "disabledUnderlineColor: #fff" );
|
||||||
ui.applyStyle( "hoverColor: #fff" );
|
ui.applyStyle( "hoverColor: #fff" );
|
||||||
ui.applyStyle( "focusColor: #fff" );
|
ui.applyStyle( "focusColor: #fff" );
|
||||||
@@ -1067,8 +1085,11 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( b, "tab.underlineColor: #fff" );
|
ui.applyStyle( b, "tab.underlineColor: #fff" );
|
||||||
ui.applyStyle( b, "tab.disabledUnderlineColor: #fff" );
|
ui.applyStyle( b, "tab.disabledUnderlineColor: #fff" );
|
||||||
ui.applyStyle( b, "tab.selectedBackground: #fff" );
|
ui.applyStyle( b, "tab.selectedBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "tab.selectedForeground: #fff" );
|
||||||
ui.applyStyle( b, "tab.hoverBackground: #fff" );
|
ui.applyStyle( b, "tab.hoverBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "tab.hoverForeground: #fff" );
|
||||||
ui.applyStyle( b, "tab.focusBackground: #fff" );
|
ui.applyStyle( b, "tab.focusBackground: #fff" );
|
||||||
|
ui.applyStyle( b, "tab.focusForeground: #fff" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
|||||||
*/
|
*/
|
||||||
public class TestUtils
|
public class TestUtils
|
||||||
{
|
{
|
||||||
public static final float[] FACTORS = new float[] { 1f }; //, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
public static final float[] FACTORS = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||||
|
|
||||||
public static void setup( boolean withFocus ) {
|
public static void setup( boolean withFocus ) {
|
||||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||||
|
|||||||
@@ -43,6 +43,17 @@ class BasicComponentsPanel
|
|||||||
// UIManager.put( "PasswordField.showRevealButton", true );
|
// UIManager.put( "PasswordField.showRevealButton", true );
|
||||||
passwordField1.putClientProperty( FlatClientProperties.STYLE, "showRevealButton: true" );
|
passwordField1.putClientProperty( FlatClientProperties.STYLE, "showRevealButton: true" );
|
||||||
|
|
||||||
|
// add leading/trailing icons to text fields
|
||||||
|
leadingIconTextField.putClientProperty( FlatClientProperties.PLACEHOLDER_TEXT, "Search" );
|
||||||
|
leadingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||||
|
new FlatSearchIcon() );
|
||||||
|
trailingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||||
|
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/DataTables.svg" ) );
|
||||||
|
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||||
|
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/user.svg" ) );
|
||||||
|
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||||
|
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/bookmarkGroup.svg" ) );
|
||||||
|
|
||||||
// search history button
|
// search history button
|
||||||
JButton searchHistoryButton = new JButton( new FlatSearchWithHistoryIcon( true ) );
|
JButton searchHistoryButton = new JButton( new FlatSearchWithHistoryIcon( true ) );
|
||||||
searchHistoryButton.setToolTipText( "Search History" );
|
searchHistoryButton.setToolTipText( "Search History" );
|
||||||
@@ -177,9 +188,9 @@ class BasicComponentsPanel
|
|||||||
JComboBox<String> warningHintsComboBox = new JComboBox<>();
|
JComboBox<String> warningHintsComboBox = new JComboBox<>();
|
||||||
JSpinner warningHintsSpinner = new JSpinner();
|
JSpinner warningHintsSpinner = new JSpinner();
|
||||||
JLabel iconsLabel = new JLabel();
|
JLabel iconsLabel = new JLabel();
|
||||||
JTextField leadingIconTextField = new JTextField();
|
leadingIconTextField = new JTextField();
|
||||||
JTextField trailingIconTextField = new JTextField();
|
trailingIconTextField = new JTextField();
|
||||||
JTextField iconsTextField = new JTextField();
|
iconsTextField = new JTextField();
|
||||||
JLabel compsLabel = new JLabel();
|
JLabel compsLabel = new JLabel();
|
||||||
compsTextField = new JTextField();
|
compsTextField = new JTextField();
|
||||||
clearTextField = new JTextField();
|
clearTextField = new JTextField();
|
||||||
@@ -851,17 +862,6 @@ class BasicComponentsPanel
|
|||||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||||
|
|
||||||
// add leading/trailing icons to text fields
|
|
||||||
leadingIconTextField.putClientProperty( FlatClientProperties.PLACEHOLDER_TEXT, "Search" );
|
|
||||||
leadingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
|
||||||
new FlatSearchIcon() );
|
|
||||||
trailingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
|
||||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/DataTables.svg" ) );
|
|
||||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
|
||||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/user.svg" ) );
|
|
||||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
|
||||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/bookmarkGroup.svg" ) );
|
|
||||||
|
|
||||||
if( FlatLafDemo.screenshotsMode ) {
|
if( FlatLafDemo.screenshotsMode ) {
|
||||||
// hide some components
|
// hide some components
|
||||||
Component[] hiddenComponents = {
|
Component[] hiddenComponents = {
|
||||||
@@ -919,6 +919,9 @@ class BasicComponentsPanel
|
|||||||
|
|
||||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
private JPasswordField passwordField1;
|
private JPasswordField passwordField1;
|
||||||
|
private JTextField leadingIconTextField;
|
||||||
|
private JTextField trailingIconTextField;
|
||||||
|
private JTextField iconsTextField;
|
||||||
private JTextField compsTextField;
|
private JTextField compsTextField;
|
||||||
private JTextField clearTextField;
|
private JTextField clearTextField;
|
||||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
|||||||
@@ -659,18 +659,27 @@ new FormModel {
|
|||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
name: "leadingIconTextField"
|
name: "leadingIconTextField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 1 14,growx"
|
"value": "cell 1 14,growx"
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
name: "trailingIconTextField"
|
name: "trailingIconTextField"
|
||||||
"text": "text"
|
"text": "text"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 2 14,growx"
|
"value": "cell 2 14,growx"
|
||||||
} )
|
} )
|
||||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
name: "iconsTextField"
|
name: "iconsTextField"
|
||||||
"text": "text"
|
"text": "text"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 3 14,growx"
|
"value": "cell 3 14,growx"
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ class ControlBar
|
|||||||
|
|
||||||
// initialize look and feels combo box
|
// initialize look and feels combo box
|
||||||
DefaultComboBoxModel<LookAndFeelInfo> lafModel = new DefaultComboBoxModel<>();
|
DefaultComboBoxModel<LookAndFeelInfo> lafModel = new DefaultComboBoxModel<>();
|
||||||
lafModel.addElement( new LookAndFeelInfo( "Flat Light (F1)", FlatLightLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Light (F1)", FlatLightLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "Flat Dark (F2)", FlatDarkLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Dark (F2)", FlatDarkLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "Flat IntelliJ (F3)", FlatIntelliJLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf IntelliJ (F3)", FlatIntelliJLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "Flat Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
||||||
|
|
||||||
UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
|
UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
|
||||||
for( UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels ) {
|
for( UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels ) {
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ import com.formdev.flatlaf.FlatLightLaf;
|
|||||||
import com.formdev.flatlaf.demo.HintManager.Hint;
|
import com.formdev.flatlaf.demo.HintManager.Hint;
|
||||||
import com.formdev.flatlaf.demo.extras.*;
|
import com.formdev.flatlaf.demo.extras.*;
|
||||||
import com.formdev.flatlaf.demo.intellijthemes.*;
|
import com.formdev.flatlaf.demo.intellijthemes.*;
|
||||||
import com.formdev.flatlaf.extras.FlatDesktop;
|
|
||||||
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
|
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
|
||||||
|
import com.formdev.flatlaf.extras.FlatDesktop;
|
||||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||||
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
|
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
|
||||||
import com.formdev.flatlaf.extras.components.FlatButton;
|
import com.formdev.flatlaf.extras.components.FlatButton;
|
||||||
@@ -82,13 +82,33 @@ class DemoFrame
|
|||||||
if( tabIndex >= 0 && tabIndex < tabbedPane.getTabCount() && tabIndex != tabbedPane.getSelectedIndex() )
|
if( tabIndex >= 0 && tabIndex < tabbedPane.getTabCount() && tabIndex != tabbedPane.getSelectedIndex() )
|
||||||
tabbedPane.setSelectedIndex( tabIndex );
|
tabbedPane.setSelectedIndex( tabIndex );
|
||||||
|
|
||||||
// hide some menu items on macOS
|
// macOS (see https://www.formdev.com/flatlaf/macos/)
|
||||||
if( SystemInfo.isMacOS ) {
|
if( SystemInfo.isMacOS ) {
|
||||||
|
// hide menu items that are in macOS application menu
|
||||||
exitMenuItem.setVisible( false );
|
exitMenuItem.setVisible( false );
|
||||||
aboutMenuItem.setVisible( false );
|
aboutMenuItem.setVisible( false );
|
||||||
|
|
||||||
// do not use HTML text on macOS
|
// do not use HTML text in menu items because this is not supported in macOS screen menu
|
||||||
htmlMenuItem.setText( "some text" );
|
htmlMenuItem.setText( "some text" );
|
||||||
|
|
||||||
|
if( SystemInfo.isMacFullWindowContentSupported ) {
|
||||||
|
// expand window content into window title bar and make title bar transparent
|
||||||
|
getRootPane().putClientProperty( "apple.awt.fullWindowContent", true );
|
||||||
|
getRootPane().putClientProperty( "apple.awt.transparentTitleBar", true );
|
||||||
|
|
||||||
|
// hide window title
|
||||||
|
if( SystemInfo.isJava_17_orLater )
|
||||||
|
getRootPane().putClientProperty( "apple.awt.windowTitleVisible", false );
|
||||||
|
else
|
||||||
|
setTitle( null );
|
||||||
|
|
||||||
|
// add gap to left side of toolbar
|
||||||
|
toolBar.add( Box.createHorizontalStrut( 70 ), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable full screen mode for this window (for Java 8 - 10; not necessary for Java 11+)
|
||||||
|
if( !SystemInfo.isJava_11_orLater )
|
||||||
|
getRootPane().putClientProperty( "apple.awt.fullscreenable", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
// integrate into macOS screen menu
|
// integrate into macOS screen menu
|
||||||
@@ -433,9 +453,9 @@ class DemoFrame
|
|||||||
lafClass == FlatIntelliJLaf.class ||
|
lafClass == FlatIntelliJLaf.class ||
|
||||||
lafClass == FlatDarculaLaf.class;
|
lafClass == FlatDarculaLaf.class;
|
||||||
|
|
||||||
accentColorLabel.setEnabled( isAccentColorSupported );
|
accentColorLabel.setVisible( isAccentColorSupported );
|
||||||
for( int i = 0; i < accentColorButtons.length; i++ )
|
for( int i = 0; i < accentColorButtons.length; i++ )
|
||||||
accentColorButtons[i].setEnabled( isAccentColorSupported );
|
accentColorButtons[i].setVisible( isAccentColorSupported );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
@@ -464,6 +484,7 @@ class DemoFrame
|
|||||||
JMenuItem projectViewMenuItem = new JMenuItem();
|
JMenuItem projectViewMenuItem = new JMenuItem();
|
||||||
JMenuItem structureViewMenuItem = new JMenuItem();
|
JMenuItem structureViewMenuItem = new JMenuItem();
|
||||||
JMenuItem propertiesViewMenuItem = new JMenuItem();
|
JMenuItem propertiesViewMenuItem = new JMenuItem();
|
||||||
|
scrollingPopupMenu = new JMenu();
|
||||||
JMenuItem menuItem2 = new JMenuItem();
|
JMenuItem menuItem2 = new JMenuItem();
|
||||||
htmlMenuItem = new JMenuItem();
|
htmlMenuItem = new JMenuItem();
|
||||||
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
|
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
|
||||||
@@ -668,6 +689,12 @@ class DemoFrame
|
|||||||
}
|
}
|
||||||
viewMenu.add(menu1);
|
viewMenu.add(menu1);
|
||||||
|
|
||||||
|
//======== scrollingPopupMenu ========
|
||||||
|
{
|
||||||
|
scrollingPopupMenu.setText("Scrolling Popup Menu");
|
||||||
|
}
|
||||||
|
viewMenu.add(scrollingPopupMenu);
|
||||||
|
|
||||||
//---- menuItem2 ----
|
//---- menuItem2 ----
|
||||||
menuItem2.setText("Disabled Item");
|
menuItem2.setText("Disabled Item");
|
||||||
menuItem2.setEnabled(false);
|
menuItem2.setEnabled(false);
|
||||||
@@ -889,7 +916,16 @@ class DemoFrame
|
|||||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||||
|
|
||||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
scrollingPopupMenu.add( "Large menus are scrollable" );
|
||||||
|
scrollingPopupMenu.add( "Use mouse wheel to scroll" );
|
||||||
|
scrollingPopupMenu.add( "Or use up/down arrows at top/bottom" );
|
||||||
|
for( int i = 1; i <= 100; i++ )
|
||||||
|
scrollingPopupMenu.add( "Item " + i );
|
||||||
|
|
||||||
|
if( FlatLaf.supportsNativeWindowDecorations() || (SystemInfo.isLinux && JFrame.isDefaultLookAndFeelDecorated()) ) {
|
||||||
|
if( SystemInfo.isLinux )
|
||||||
|
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||||
|
else
|
||||||
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
||||||
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||||
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||||
@@ -931,6 +967,7 @@ class DemoFrame
|
|||||||
|
|
||||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
private JMenuItem exitMenuItem;
|
private JMenuItem exitMenuItem;
|
||||||
|
private JMenu scrollingPopupMenu;
|
||||||
private JMenuItem htmlMenuItem;
|
private JMenuItem htmlMenuItem;
|
||||||
private JMenu fontMenu;
|
private JMenu fontMenu;
|
||||||
private JMenu optionsMenu;
|
private JMenu optionsMenu;
|
||||||
|
|||||||
@@ -282,6 +282,13 @@ new FormModel {
|
|||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||||
} )
|
} )
|
||||||
} )
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||||
|
name: "scrollingPopupMenu"
|
||||||
|
"text": "Scrolling Popup Menu"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
name: "menuItem2"
|
name: "menuItem2"
|
||||||
"text": "Disabled Item"
|
"text": "Disabled Item"
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
package com.formdev.flatlaf.demo;
|
package com.formdev.flatlaf.demo;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JFrame;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.extras.FlatInspector;
|
import com.formdev.flatlaf.extras.FlatInspector;
|
||||||
@@ -34,7 +36,7 @@ public class FlatLafDemo
|
|||||||
static boolean screenshotsMode = Boolean.parseBoolean( System.getProperty( "flatlaf.demo.screenshotsMode" ) );
|
static boolean screenshotsMode = Boolean.parseBoolean( System.getProperty( "flatlaf.demo.screenshotsMode" ) );
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
// macOS
|
// macOS (see https://www.formdev.com/flatlaf/macos/)
|
||||||
if( SystemInfo.isMacOS ) {
|
if( SystemInfo.isMacOS ) {
|
||||||
// enable screen menu bar
|
// enable screen menu bar
|
||||||
// (moves menu bar from JFrame window to top of screen)
|
// (moves menu bar from JFrame window to top of screen)
|
||||||
@@ -49,9 +51,17 @@ 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)
|
||||||
System.setProperty( "apple.awt.application.appearance", "system" );
|
System.setProperty( "apple.awt.application.appearance", "system" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
if( SystemInfo.isLinux ) {
|
||||||
|
// enable custom window decorations
|
||||||
|
JFrame.setDefaultLookAndFeelDecorated( true );
|
||||||
|
JDialog.setDefaultLookAndFeelDecorated( true );
|
||||||
|
}
|
||||||
|
|
||||||
if( FlatLafDemo.screenshotsMode && !SystemInfo.isJava_9_orLater && System.getProperty( "flatlaf.uiScale" ) == null )
|
if( FlatLafDemo.screenshotsMode && !SystemInfo.isJava_9_orLater && System.getProperty( "flatlaf.uiScale" ) == null )
|
||||||
System.setProperty( "flatlaf.uiScale", "2x" );
|
System.setProperty( "flatlaf.uiScale", "2x" );
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user