mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 22:47:13 -06:00
Compare commits
30 Commits
fonts/inte
...
smooth-scr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44a04cca2c | ||
|
|
b32b8db97a | ||
|
|
c529dcb747 | ||
|
|
04658c2ef0 | ||
|
|
5cdef5409b | ||
|
|
6dfc204e40 | ||
|
|
542e7d5f60 | ||
|
|
3628a03c9d | ||
|
|
6ce2198cd6 | ||
|
|
e2e3fd31e9 | ||
|
|
cf70cfb50c | ||
|
|
29f6c5fae9 | ||
|
|
419a689ca4 | ||
|
|
865a56875f | ||
|
|
3573188025 | ||
|
|
1f2622819a | ||
|
|
305e9e602e | ||
|
|
1ae31588c4 | ||
|
|
d64a8e93e1 | ||
|
|
e603bd81a1 | ||
|
|
522ebb6fa3 | ||
|
|
7a582c2d1f | ||
|
|
762fe89867 | ||
|
|
1ebfe00f3c | ||
|
|
fdabca99b2 | ||
|
|
736305849a | ||
|
|
889b5ea56a | ||
|
|
82514ccbfc | ||
|
|
b67b701d1e | ||
|
|
7f226a2742 |
19
.github/workflows/ci.yml
vendored
19
.github/workflows/ci.yml
vendored
@@ -19,24 +19,25 @@ jobs:
|
|||||||
# test against
|
# test against
|
||||||
# - Java 8 (minimum requirement)
|
# - Java 8 (minimum requirement)
|
||||||
# - Java LTS versions (11, 17, ...)
|
# - Java LTS versions (11, 17, ...)
|
||||||
# - latest Java version(s)
|
# - lastest Java version(s)
|
||||||
java:
|
java:
|
||||||
- 8
|
- 8
|
||||||
- 11 # LTS
|
- 11 # LTS
|
||||||
- 17 # LTS
|
- 17 # LTS
|
||||||
|
- 19
|
||||||
toolchain: [""]
|
toolchain: [""]
|
||||||
include:
|
include:
|
||||||
- java: 17
|
- java: 17
|
||||||
toolchain: 21 # latest
|
toolchain: 20 # latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
if: matrix.java == '8'
|
if: matrix.java == '8'
|
||||||
|
|
||||||
- name: Setup Java ${{ matrix.java }}
|
- name: Setup Java ${{ matrix.java }}
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
distribution: temurin # Java 8, 11 and 17 are pre-installed on ubuntu-latest
|
distribution: temurin # Java 8, 11 and 17 are pre-installed on ubuntu-latest
|
||||||
@@ -50,7 +51,7 @@ jobs:
|
|||||||
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
if: matrix.java == '11'
|
if: matrix.java == '11'
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-build-artifacts
|
name: FlatLaf-build-artifacts
|
||||||
@@ -70,10 +71,10 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
@@ -106,10 +107,10 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
|||||||
4
.github/workflows/fonts.yml
vendored
4
.github/workflows/fonts.yml
vendored
@@ -30,10 +30,10 @@ jobs:
|
|||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin # pre-installed on ubuntu-latest
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
|||||||
7
.github/workflows/natives.yml
vendored
7
.github/workflows/natives.yml
vendored
@@ -20,18 +20,17 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
- windows
|
- windows
|
||||||
- macos
|
|
||||||
- ubuntu
|
- ubuntu
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
@@ -43,7 +42,7 @@ jobs:
|
|||||||
run: ./gradlew build-natives --no-daemon
|
run: ./gradlew build-natives --no-daemon
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
131
CHANGELOG.md
131
CHANGELOG.md
@@ -1,136 +1,6 @@
|
|||||||
FlatLaf Change Log
|
FlatLaf Change Log
|
||||||
==================
|
==================
|
||||||
|
|
||||||
## 3.4-SNAPSHOT
|
|
||||||
|
|
||||||
#### New features and improvements
|
|
||||||
|
|
||||||
- Native libraries: System property `flatlaf.nativeLibraryPath` now supports
|
|
||||||
loading native libraries named the same as on Maven central. Improved log
|
|
||||||
messages for loading fails.
|
|
||||||
- Fonts: Updated **Inter** to
|
|
||||||
[v4.0](https://github.com/rsms/inter/releases/tag/v4.0).
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- JIDE CommandMenuBar: Fixed `ClassCastException` when JIDE command bar displays
|
|
||||||
`JideMenu` in popup. (PR #794)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.3
|
|
||||||
|
|
||||||
#### New features and improvements
|
|
||||||
|
|
||||||
- macOS (10.14+): Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
|
||||||
native macOS rounded borders. (PR #772; issue #715)
|
|
||||||
- Native libraries: Added `libflatlaf-macos-arm64.dylib` and
|
|
||||||
`libflatlaf-macos-x86_64.dylib`. See also
|
|
||||||
https://www.formdev.com/flatlaf/native-libraries/.
|
|
||||||
- ScrollPane: Support rounded border. (PR #713)
|
|
||||||
- SplitPane: Support divider hover and pressed background colors. (PR #788)
|
|
||||||
- TabbedPane: Support vertical tabs. (PR #758, issue #633)
|
|
||||||
- TabbedPane: Paint rounded tab area background for rounded cards. (issue #717)
|
|
||||||
- ToolBar: Added styling properties `separatorWidth` and `separatorColor`.
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Button and ToggleButton: Selected buttons did not use explicitly set
|
|
||||||
foreground color. (issue 756)
|
|
||||||
- FileChooser: Catch NPE in Java 21 when getting icon for `.exe` files that use
|
|
||||||
default Windows exe icon. (see
|
|
||||||
[JDK-8320692](https://bugs.openjdk.org/browse/JDK-8320692))
|
|
||||||
- OptionPane: Fixed styling custom panel background in `JOptionPane`. (issue
|
|
||||||
#761)
|
|
||||||
- ScrollPane: Styling ScrollPane border properties did not work if view
|
|
||||||
component is a Table.
|
|
||||||
- Table:
|
|
||||||
- Switching theme looses table grid and intercell spacing. (issues #733 and
|
|
||||||
#750)
|
|
||||||
- Fixed background of `boolean` columns when using alternating row colors.
|
|
||||||
(issue #780)
|
|
||||||
- Fixed border arc of components in complex table cell editors. (issue #786)
|
|
||||||
- TableHeader:
|
|
||||||
- No longer temporary replace header cell renderer while painting. This avoids
|
|
||||||
a `StackOverflowError` in case that custom renderer does this too. (see
|
|
||||||
[NetBeans issue #6835](https://github.com/apache/netbeans/issues/6835)) This
|
|
||||||
also improves compatibility with custom table header implementations.
|
|
||||||
- Header cell renderer background/foreground colors were not restored after
|
|
||||||
hover if renderer uses `null` for background/foreground. (PR #790)
|
|
||||||
- TabbedPane:
|
|
||||||
- Avoid unnecessary repainting whole tabbed pane content area when layouting
|
|
||||||
leading/trailing components.
|
|
||||||
- Avoid unnecessary repainting of selected tab on temporary changes.
|
|
||||||
- Fixed "endless" layouting and repainting when using nested tabbed panes (top
|
|
||||||
and bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping)
|
|
||||||
as tab content. (see
|
|
||||||
[jadx issue #2030](https://github.com/skylot/jadx/issues/2030))
|
|
||||||
- Fixed broken rendering after resizing window to minimum size and then
|
|
||||||
increasing size again. (issue #767)
|
|
||||||
|
|
||||||
#### Incompatibilities
|
|
||||||
|
|
||||||
- Removed support for JetBrains custom decorations, which required
|
|
||||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki) (JBR)
|
|
||||||
8 or 11. It did not work for JBR 17. System property
|
|
||||||
`flatlaf.useJetBrainsCustomDecorations` is now ignored. **Note**: FlatLaf
|
|
||||||
window decorations continue to work with JBR.
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2.5
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Popup: Fixed NPE if popup invoker is `null` on Windows 10. (issue #753;
|
|
||||||
regression in 3.2.1 in fix for #626)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2.4
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Popup: Fixed NPE if popup invoker is `null` on Linux with Wayland and Java 21.
|
|
||||||
(issue #752; regression in 3.2.3)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2.3
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Popup: Popups that request focus were not shown on Linux with Wayland and Java 21.
|
|
||||||
(issue #752)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2.2
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Button: Fixed painting icon and text at wrong location when using HTML text,
|
|
||||||
left/right vertical alignment and running in Java 19+. (issue #746)
|
|
||||||
- CheckBox and RadioButton: Fixed cut off right side when border is removed and
|
|
||||||
horizontal alignment is set to `right`. (issue #734)
|
|
||||||
- TabbedPane: Fixed NPE when using focusable component as tab component and
|
|
||||||
switching theme. (issue #745)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2.1
|
|
||||||
|
|
||||||
#### Fixed bugs
|
|
||||||
|
|
||||||
- Fixed memory leak in
|
|
||||||
`MultiResolutionImageSupport.create(int,Dimension[],Function<Dimension,Image>)`,
|
|
||||||
which caches images created by the producer function. Used by
|
|
||||||
`FlatSVGIcon.getImage()` and `FlatSVGUtils.createWindowIconImages()`. If you
|
|
||||||
use one of these methods, it is **strongly recommended** to upgrade to this
|
|
||||||
version, because if the returned image is larger and painted very often it may
|
|
||||||
result in an out-of-memory situation. (issue #726)
|
|
||||||
- FileChooser: Fixed occasional NPE in `FlatShortcutsPanel` on Windows. (issue
|
|
||||||
#718)
|
|
||||||
- TextField: Fixed placeholder text painting, which did not respect horizontal
|
|
||||||
alignment property of `JTextField`. (issue #721)
|
|
||||||
- Popup: Fixed drop shadow if popup overlaps a heavyweight component. (Windows
|
|
||||||
10 only; issue #626)
|
|
||||||
|
|
||||||
|
|
||||||
## 3.2
|
## 3.2
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
@@ -253,6 +123,7 @@ FlatLaf Change Log
|
|||||||
- Windows DLLs are now digitally signed with FormDev Software GmbH
|
- Windows DLLs are now digitally signed with FormDev Software GmbH
|
||||||
certificate.
|
certificate.
|
||||||
|
|
||||||
|
|
||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
|
|
||||||
- FlatLaf window decorations:
|
- FlatLaf window decorations:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ build script:
|
|||||||
artifactId: flatlaf
|
artifactId: flatlaf
|
||||||
version: (see button below)
|
version: (see button below)
|
||||||
|
|
||||||
Otherwise, download `flatlaf-<version>.jar` here:
|
Otherwise download `flatlaf-<version>.jar` here:
|
||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
||||||
|
|
||||||
@@ -141,6 +141,7 @@ details and downloads.
|
|||||||
Buzz
|
Buzz
|
||||||
----
|
----
|
||||||
|
|
||||||
|
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
||||||
- [FlatLaf 3.1 (and 3.0) announcement on Reddit](https://www.reddit.com/r/java/comments/12xgrsu/flatlaf_31_and_30_swing_look_and_feel/)
|
- [FlatLaf 3.1 (and 3.0) announcement on Reddit](https://www.reddit.com/r/java/comments/12xgrsu/flatlaf_31_and_30_swing_look_and_feel/)
|
||||||
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
||||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class ReorderJarEntries
|
|||||||
// 1st pass: copy .properties files
|
// 1st pass: copy .properties files
|
||||||
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
||||||
|
|
||||||
// 2nd pass: copy other files
|
// 2st pass: copy other files
|
||||||
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ tasks {
|
|||||||
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
||||||
dependsOn( ":flatlaf-core:compileJava" )
|
dependsOn( ":flatlaf-core:compileJava" )
|
||||||
|
|
||||||
from( project( ":flatlaf-core" ).layout.buildDirectory.dir( "generated/jni-headers" ) )
|
from( project( ":flatlaf-core" ).buildDir.resolve( "generated/jni-headers" ) )
|
||||||
into( "src/main/headers" )
|
into( "src/main/headers" )
|
||||||
include( extension.headers )
|
include( extension.headers )
|
||||||
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ java {
|
|||||||
tasks {
|
tasks {
|
||||||
compileJava {
|
compileJava {
|
||||||
// generate JNI headers
|
// generate JNI headers
|
||||||
options.headerOutputDirectory.set( layout.buildDirectory.dir( "generated/jni-headers" ) )
|
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
@@ -127,11 +127,9 @@ flatlafPublish {
|
|||||||
|
|
||||||
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
||||||
nativeArtifacts = listOf(
|
nativeArtifacts = listOf(
|
||||||
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
|
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
|
||||||
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
|
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
|
||||||
NativeArtifact( "${natives}/flatlaf-windows-arm64.dll", "windows-arm64", "dll" ),
|
NativeArtifact( "${natives}/flatlaf-windows-arm64.dll", "windows-arm64", "dll" ),
|
||||||
NativeArtifact( "${natives}/libflatlaf-macos-arm64.dylib", "macos-arm64", "dylib" ),
|
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
|
||||||
NativeArtifact( "${natives}/libflatlaf-macos-x86_64.dylib", "macos-x86_64", "dylib" ),
|
|
||||||
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Signature file v4.1
|
#Signature file v4.1
|
||||||
#Version 3.3
|
#Version 3.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"
|
||||||
@@ -23,7 +23,6 @@ fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placehol
|
|||||||
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
|
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
|
||||||
fld public final static java.lang.String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted"
|
fld public final static java.lang.String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted"
|
||||||
fld public final static java.lang.String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight"
|
fld public final static java.lang.String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight"
|
||||||
fld public final static java.lang.String POPUP_ROUNDED_BORDER_WIDTH = "Popup.roundedBorderWidth"
|
|
||||||
fld public final static java.lang.String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight"
|
fld public final static java.lang.String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight"
|
||||||
fld public final static java.lang.String PROGRESS_BAR_SQUARE = "JProgressBar.square"
|
fld public final static java.lang.String PROGRESS_BAR_SQUARE = "JProgressBar.square"
|
||||||
fld public final static java.lang.String SCROLL_BAR_SHOW_BUTTONS = "JScrollBar.showButtons"
|
fld public final static java.lang.String SCROLL_BAR_SHOW_BUTTONS = "JScrollBar.showButtons"
|
||||||
@@ -68,11 +67,6 @@ 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_ROTATION = "JTabbedPane.tabRotation"
|
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_AUTO = "auto"
|
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_LEFT = "left"
|
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_NONE = "none"
|
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_RIGHT = "right"
|
|
||||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType"
|
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_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_TYPE_UNDERLINED = "underlined"
|
||||||
@@ -247,7 +241,7 @@ meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.Strin
|
|||||||
meth public void uninitialize()
|
meth public void uninitialize()
|
||||||
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||||
supr javax.swing.plaf.basic.BasicLookAndFeel
|
supr javax.swing.plaf.basic.BasicLookAndFeel
|
||||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,updateUIPending
|
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,getUIMethod,getUIMethodInitialized,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,updateUIPending
|
||||||
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
||||||
|
|
||||||
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
||||||
@@ -288,7 +282,6 @@ fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.ui
|
|||||||
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
||||||
fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange"
|
fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange"
|
||||||
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
||||||
anno 0 java.lang.Deprecated()
|
|
||||||
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
||||||
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
||||||
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public interface FlatClientProperties
|
|||||||
//---- JButton ------------------------------------------------------------
|
//---- JButton ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies type of button.
|
* Specifies type of a button.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
@@ -278,13 +278,12 @@ public interface FlatClientProperties
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that this is not available on all platforms since it requires special support.
|
* Note that this is not available on all platforms since it requires special support.
|
||||||
* Supported platforms:
|
* Supported platforms:
|
||||||
* <ul>
|
* <p>
|
||||||
* <li><strong>Windows 11</strong>: Only two corner radiuses are supported
|
* <strong>Windows 11</strong> (x86 or x86_64): Only two corner radiuses are supported
|
||||||
* by the OS: {@code DWMWCP_ROUND} is 8px and {@code DWMWCP_ROUNDSMALL} is 4px.
|
* by the OS: {@code DWMWCP_ROUND} is 8px and {@code DWMWCP_ROUNDSMALL} is 4px.
|
||||||
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
|
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
|
||||||
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
|
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
|
||||||
* <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported.
|
* <p>
|
||||||
* </ul>
|
|
||||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||||
*
|
*
|
||||||
@@ -292,24 +291,6 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius";
|
String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius";
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the popup rounded border width if the component is shown in a popup
|
|
||||||
* or if the component is the owner of another component that is shown in a popup.
|
|
||||||
* <p>
|
|
||||||
* Only used if popup uses rounded border.
|
|
||||||
* <p>
|
|
||||||
* Note that this is not available on all platforms since it requires special support.
|
|
||||||
* Supported platforms:
|
|
||||||
* <ul>
|
|
||||||
* <li><strong>macOS</strong> (10.14 and later)
|
|
||||||
* </ul>
|
|
||||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br>
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String POPUP_ROUNDED_BORDER_WIDTH = "Popup.roundedBorderWidth";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||||
* or if the component is the owner of another component that is shown in a popup.
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
@@ -421,10 +402,10 @@ public interface FlatClientProperties
|
|||||||
String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle";
|
String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the "iconify" button should be shown in the window title bar
|
* Specifies whether the "iconfify" button should be shown in the window title bar
|
||||||
* (requires enabled window decorations). Default is {@code true}.
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
* <p>
|
* <p>
|
||||||
* Setting this shows/hides the "iconify" button
|
* Setting this shows/hides the "iconfify" button
|
||||||
* for the {@code JFrame} that contains the root pane.
|
* for the {@code JFrame} that contains the root pane.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
@@ -506,7 +487,7 @@ public interface FlatClientProperties
|
|||||||
* On macOS, Java supports this out of the box.
|
* On macOS, Java supports this out of the box.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that this client property must be set before the window becomes displayable.
|
* Note that this client property must be set before the window becomes displayable.
|
||||||
* Otherwise, an {@link IllegalComponentStateException} is thrown.
|
* Otherwise an {@link IllegalComponentStateException} is thrown.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
@@ -951,59 +932,6 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement";
|
String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement";
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the rotation of the tabs (title, icon, etc.).
|
|
||||||
* <p>
|
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.String}<br>
|
|
||||||
* <strong>Allowed Values</strong>
|
|
||||||
* {@link SwingConstants#LEFT},
|
|
||||||
* {@link SwingConstants#RIGHT},
|
|
||||||
* {@link #TABBED_PANE_TAB_ROTATION_NONE}, (default)
|
|
||||||
* {@link #TABBED_PANE_TAB_ROTATION_AUTO},
|
|
||||||
* {@link #TABBED_PANE_TAB_ROTATION_LEFT} or
|
|
||||||
* {@link #TABBED_PANE_TAB_ROTATION_RIGHT}
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String TABBED_PANE_TAB_ROTATION = "JTabbedPane.tabRotation";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tabs are not rotated.
|
|
||||||
*
|
|
||||||
* @see #TABBED_PANE_TAB_ROTATION
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String TABBED_PANE_TAB_ROTATION_NONE = "none";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tabs are rotated depending on tab placement.
|
|
||||||
* <p>
|
|
||||||
* For top and bottom tab placement, the tabs are not rotated.<br>
|
|
||||||
* For left tab placement, the tabs are rotated counter-clockwise.<br>
|
|
||||||
* For right tab placement, the tabs are rotated clockwise.
|
|
||||||
*
|
|
||||||
* @see #TABBED_PANE_TAB_ROTATION
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String TABBED_PANE_TAB_ROTATION_AUTO = "auto";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tabs are rotated counter-clockwise.
|
|
||||||
*
|
|
||||||
* @see #TABBED_PANE_TAB_ROTATION
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String TABBED_PANE_TAB_ROTATION_LEFT = "left";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tabs are rotated clockwise.
|
|
||||||
*
|
|
||||||
* @see #TABBED_PANE_TAB_ROTATION
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
String TABBED_PANE_TAB_ROTATION_RIGHT = "right";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class FlatInputMaps
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// join ltr and rtl bindings to fix up/down/etc. keys in right-to-left component orientation
|
// join ltr and rtl bindings to fix up/down/etc keys in right-to-left component orientation
|
||||||
Object[] bindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings" );
|
Object[] bindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings" );
|
||||||
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
||||||
if( bindings != null && rtlBindings != null ) {
|
if( bindings != null && rtlBindings != null ) {
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ import java.awt.image.ImageProducer;
|
|||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -75,7 +78,6 @@ import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
|||||||
import com.formdev.flatlaf.ui.FlatPopupFactory;
|
import com.formdev.flatlaf.ui.FlatPopupFactory;
|
||||||
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.ui.JavaCompatibility2;
|
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.FontUtils;
|
import com.formdev.flatlaf.util.FontUtils;
|
||||||
import com.formdev.flatlaf.util.GrayFilter;
|
import com.formdev.flatlaf.util.GrayFilter;
|
||||||
@@ -181,11 +183,17 @@ public abstract class FlatLaf
|
|||||||
* 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/11 (see exception below)
|
* This method returns {@code true} on Windows 10/11 (see exception below)
|
||||||
* and on Linux, otherwise returns {@code false}.
|
* and on Linux, {@code false} otherwise.
|
||||||
* <p>
|
|
||||||
* Returns also {@code false} on Windows 10/11 if
|
|
||||||
* FlatLaf native window border support is available (requires Windows 10/11).
|
|
||||||
* <p>
|
* <p>
|
||||||
|
* Returns also {@code false} on Windows 10/11 if:
|
||||||
|
* <ul>
|
||||||
|
* <li>FlatLaf native window border support is available (requires Windows 10/11)</li>
|
||||||
|
* <li>running in
|
||||||
|
* <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>)
|
||||||
|
* and JBR supports custom window decorations
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
* In these 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.
|
||||||
@@ -1287,8 +1295,8 @@ public abstract class FlatLaf
|
|||||||
* @since 2.5
|
* @since 2.5
|
||||||
*/
|
*/
|
||||||
public static Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
public static Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
ComponentUI ui = JavaCompatibility2.getUI( c );
|
StyleableUI ui = getStyleableUI( c );
|
||||||
return (ui instanceof StyleableUI) ? ((StyleableUI)ui).getStyleableInfos( c ) : null;
|
return (ui != null) ? ui.getStyleableInfos( c ) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1300,10 +1308,41 @@ public abstract class FlatLaf
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
public static <T> T getStyleableValue( JComponent c, String key ) {
|
public static <T> T getStyleableValue( JComponent c, String key ) {
|
||||||
ComponentUI ui = JavaCompatibility2.getUI( c );
|
StyleableUI ui = getStyleableUI( c );
|
||||||
return (ui instanceof StyleableUI) ? (T) ((StyleableUI)ui).getStyleableValue( c, key ) : null;
|
return (ui != null) ? (T) ui.getStyleableValue( c, key ) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static StyleableUI getStyleableUI( JComponent c ) {
|
||||||
|
if( !getUIMethodInitialized ) {
|
||||||
|
getUIMethodInitialized = true;
|
||||||
|
|
||||||
|
if( SystemInfo.isJava_9_orLater ) {
|
||||||
|
try {
|
||||||
|
// JComponent.getUI() is available since Java 9
|
||||||
|
getUIMethod = MethodHandles.lookup().findVirtual( JComponent.class, "getUI",
|
||||||
|
MethodType.methodType( ComponentUI.class ) );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object ui;
|
||||||
|
if( getUIMethod != null )
|
||||||
|
ui = getUIMethod.invoke( c );
|
||||||
|
else
|
||||||
|
ui = c.getClass().getMethod( "getUI" ).invoke( c );
|
||||||
|
return (ui instanceof StyleableUI) ? (StyleableUI) ui : null;
|
||||||
|
} catch( Throwable ex ) {
|
||||||
|
// ignore
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean getUIMethodInitialized;
|
||||||
|
private static MethodHandle getUIMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the preferred font family to be used for (nearly) all fonts; or {@code null}.
|
* Returns the preferred font family to be used for (nearly) all fonts; or {@code null}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -103,10 +103,7 @@ public interface FlatSystemProperties
|
|||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||||
*
|
|
||||||
* @deprecated No longer used since FlatLaf 3.3. Retained for API compatibility.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,6 +132,14 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String ANIMATION = "flatlaf.animation";
|
String ANIMATION = "flatlaf.animation";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether smooth scrolling is enabled.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*/
|
||||||
|
String SMOOTH_SCROLLING = "flatlaf.smoothScrolling";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
|
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -172,33 +177,19 @@ public interface FlatSystemProperties
|
|||||||
String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary";
|
String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a directory in which the FlatLaf native libraries are searched for.
|
* Specifies a directory in which the native FlatLaf libraries have been extracted.
|
||||||
* The path can be absolute or relative to current application working directory.
|
* The path can be absolute or relative to current application working directory.
|
||||||
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
|
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
|
||||||
* <p>
|
* <p>
|
||||||
* If the value is {@code "system"} (supported since FlatLaf 2.6),
|
* If the value is {@code "system"}, then {@link System#loadLibrary(String)} is
|
||||||
* then {@link System#loadLibrary(String)} is used to load the native library.
|
* used to load the native library.
|
||||||
* This searches for the native library in classloader of caller
|
* Searches for the native library in classloader of caller
|
||||||
* (using {@link ClassLoader#findLibrary(String)}) and in paths specified
|
* (using {@link ClassLoader#findLibrary(String)}) and in paths specified
|
||||||
* in system properties {@code sun.boot.library.path} and {@code java.library.path}.
|
* in system properties {@code sun.boot.library.path} and {@code java.library.path}.
|
||||||
|
* (supported since FlatLaf 2.6)
|
||||||
* <p>
|
* <p>
|
||||||
* If the native library can not be loaded from the given path (or via {@link System#loadLibrary(String)}),
|
* If the native library can not loaded from the given path (or via {@link System#loadLibrary(String)}),
|
||||||
* then the embedded native library is extracted to the temporary directory and loaded from there.
|
* then the embedded native library is extracted to the temporary directory and loaded from there.
|
||||||
* <p>
|
|
||||||
* The file names of the native libraries must be either:
|
|
||||||
* <ul>
|
|
||||||
* <li>the same as in flatlaf.jar in package 'com/formdev/flatlaf/natives' (required for "system") or
|
|
||||||
* <li>when downloaded from Maven central then as described here:
|
|
||||||
* <a href="https://www.formdev.com/flatlaf/native-libraries/">https://www.formdev.com/flatlaf/native-libraries/</a>
|
|
||||||
* (requires FlatLaf 3.4)
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* <strong>Note</strong>: Since FlatLaf 3.1 it is recommended to download the
|
|
||||||
* FlatLaf native libraries from Maven central and distribute them with your
|
|
||||||
* application in the same directory as flatlaf.jar.
|
|
||||||
* Then it is <strong>not necessary</strong> to set this system property.
|
|
||||||
* See <a href="https://www.formdev.com/flatlaf/native-libraries/">https://www.formdev.com/flatlaf/native-libraries/</a>
|
|
||||||
* for details.
|
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ class LinuxFontPolicy
|
|||||||
* Gets the default font for KDE from 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). An application restart is necessary.
|
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
||||||
* This is the same behavior as in native KDE applications.
|
* This is the same behavior as in native KDE applications.
|
||||||
*
|
*
|
||||||
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ debug*/
|
|||||||
targetTopY = popupLocation.y;
|
targetTopY = popupLocation.y;
|
||||||
targetBottomY = popupLocation.y + popupSize.height;
|
targetBottomY = popupLocation.y + popupSize.height;
|
||||||
|
|
||||||
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
// install own event queue to supress mouse events when mouse is moved within safe triangle
|
||||||
if( subMenuEventQueue == null )
|
if( subMenuEventQueue == null )
|
||||||
subMenuEventQueue = new SubMenuEventQueue();
|
subMenuEventQueue = new SubMenuEventQueue();
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class FlatTabbedPaneCloseIcon
|
|||||||
closeSize.width, closeSize.height, closeArc, closeArc );
|
closeSize.width, closeSize.height, closeArc, closeArc );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set color of cross
|
// set cross color
|
||||||
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
||||||
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
||||||
|
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ public class FlatTreeOpenIcon
|
|||||||
double arc = 1.5;
|
double arc = 1.5;
|
||||||
double arc2 = 0.5;
|
double arc2 = 0.5;
|
||||||
path = FlatUIUtils.createPath( false,
|
path = FlatUIUtils.createPath( false,
|
||||||
// bottom-left of opened part
|
// bottom-left of opend part
|
||||||
2,13.5,
|
2,13.5,
|
||||||
// top-left of opened part
|
// top-left of opend part
|
||||||
FlatUIUtils.ROUNDED, 4.5,7.5, arc,
|
FlatUIUtils.ROUNDED, 4.5,7.5, arc,
|
||||||
// top-right of opened part
|
// top-right of opend part
|
||||||
FlatUIUtils.ROUNDED, 15.5,7.5, arc2,
|
FlatUIUtils.ROUNDED, 15.5,7.5, arc2,
|
||||||
|
|
||||||
// bottom-right
|
// bottom-right
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ 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 blurry edges when scaled (e.g. at 125% or 175%)
|
// 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 );
|
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import javax.swing.JComboBox;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSpinner;
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.JViewport;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.basic.BasicBorders;
|
import javax.swing.plaf.basic.BasicBorders;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
@@ -194,7 +195,8 @@ public class FlatBorder
|
|||||||
protected boolean isEnabled( Component c ) {
|
protected boolean isEnabled( Component c ) {
|
||||||
if( c instanceof JScrollPane ) {
|
if( c instanceof JScrollPane ) {
|
||||||
// check whether view component is disabled
|
// check whether view component is disabled
|
||||||
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
|
JViewport viewport = ((JScrollPane)c).getViewport();
|
||||||
|
Component view = (viewport != null) ? viewport.getView() : null;
|
||||||
if( view != null && !isEnabled( view ) )
|
if( view != null && !isEnabled( view ) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ import javax.swing.plaf.ToolBarUI;
|
|||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
|
||||||
import javax.swing.text.View;
|
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
||||||
@@ -553,45 +551,9 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to BasicButtonUI.paint(), but does not use zero insets for HTML text,
|
|
||||||
* which is done in BasicButtonUI.layout() since Java 19.
|
|
||||||
* See https://github.com/openjdk/jdk/pull/8407
|
|
||||||
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
g = FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c );
|
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
||||||
|
|
||||||
AbstractButton b = (AbstractButton) c;
|
|
||||||
|
|
||||||
// layout
|
|
||||||
String clippedText = layout( b, b.getFontMetrics( b.getFont() ), b.getWidth(), b.getHeight() );
|
|
||||||
|
|
||||||
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
|
||||||
clearTextShiftOffset();
|
|
||||||
|
|
||||||
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
|
||||||
ButtonModel model = b.getModel();
|
|
||||||
if( model.isArmed() && model.isPressed() )
|
|
||||||
paintButtonPressed( g, b );
|
|
||||||
|
|
||||||
// paint icon
|
|
||||||
if( b.getIcon() != null )
|
|
||||||
paintIcon( g, b, iconR );
|
|
||||||
|
|
||||||
// paint text
|
|
||||||
if( clippedText != null && !clippedText.isEmpty() ) {
|
|
||||||
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
|
||||||
if( view != null )
|
|
||||||
view.paint( g, textR ); // HTML text
|
|
||||||
else
|
|
||||||
paintText( g, b, textR, clippedText );
|
|
||||||
}
|
|
||||||
|
|
||||||
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
|
||||||
if( b.isFocusPainted() && b.hasFocus() )
|
|
||||||
paintFocus( g, b, viewR, textR, iconR );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -721,15 +683,14 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( JComponent c ) {
|
protected Color getForeground( JComponent c ) {
|
||||||
Color fg = c.getForeground();
|
|
||||||
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||||
|
|
||||||
// selected state
|
// selected state
|
||||||
if( ((AbstractButton)c).isSelected() ) {
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
toolBarButton
|
toolBarButton
|
||||||
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : fg)
|
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : c.getForeground())
|
||||||
: (isCustomForeground( fg ) ? fg : selectedForeground),
|
: selectedForeground,
|
||||||
toolBarButton
|
toolBarButton
|
||||||
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
||||||
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
||||||
@@ -741,7 +702,7 @@ public class FlatButtonUI
|
|||||||
// toolbar button
|
// toolbar button
|
||||||
if( toolBarButton ) {
|
if( toolBarButton ) {
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
fg,
|
c.getForeground(),
|
||||||
disabledText,
|
disabledText,
|
||||||
null,
|
null,
|
||||||
toolbarHoverForeground,
|
toolbarHoverForeground,
|
||||||
@@ -752,7 +713,7 @@ public class FlatButtonUI
|
|||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
getForegroundBase( c, def ),
|
getForegroundBase( c, def ),
|
||||||
disabledText,
|
disabledText,
|
||||||
isCustomForeground( fg ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
isCustomForeground( c.getForeground() ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
||||||
def ? defaultHoverForeground : hoverForeground,
|
def ? defaultHoverForeground : hoverForeground,
|
||||||
def ? defaultPressedForeground : pressedForeground );
|
def ? defaultPressedForeground : pressedForeground );
|
||||||
}
|
}
|
||||||
@@ -825,67 +786,6 @@ public class FlatButtonUI
|
|||||||
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBaseline( JComponent c, int width, int height ) {
|
|
||||||
return getBaselineImpl( c, width, height );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to BasicButtonUI.getBaseline(), but does not use zero insets for HTML text,
|
|
||||||
* which is done in BasicButtonUI.layout() since Java 19.
|
|
||||||
* See https://github.com/openjdk/jdk/pull/8407
|
|
||||||
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
|
||||||
*/
|
|
||||||
static int getBaselineImpl( JComponent c, int width, int height ) {
|
|
||||||
if( width < 0 || height < 0 )
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
|
|
||||||
AbstractButton b = (AbstractButton) c;
|
|
||||||
String text = b.getText();
|
|
||||||
if( text == null || text.isEmpty() )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
|
||||||
layout( b, fm, width, height );
|
|
||||||
|
|
||||||
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
|
||||||
if( view != null ) {
|
|
||||||
// HTML text
|
|
||||||
int baseline = BasicHTML.getHTMLBaseline( view, textR.width, textR.height );
|
|
||||||
return (baseline >= 0) ? textR.y + baseline : baseline;
|
|
||||||
} else
|
|
||||||
return textR.y + fm.getAscent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to BasicButtonUI.layout(), but does not use zero insets for HTML text,
|
|
||||||
* which is done in BasicButtonUI.layout() since Java 19.
|
|
||||||
* See https://github.com/openjdk/jdk/pull/8407
|
|
||||||
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
|
||||||
*/
|
|
||||||
private static String layout( AbstractButton b, FontMetrics fm, int width, int height ) {
|
|
||||||
// compute view rectangle
|
|
||||||
Insets insets = b.getInsets();
|
|
||||||
viewR.setBounds( insets.left, insets.top,
|
|
||||||
width - insets.left - insets.right,
|
|
||||||
height - insets.top - insets.bottom );
|
|
||||||
|
|
||||||
// reset rectangles
|
|
||||||
textR.setBounds( 0, 0, 0, 0 );
|
|
||||||
iconR.setBounds( 0, 0, 0, 0 );
|
|
||||||
|
|
||||||
String text = b.getText();
|
|
||||||
return SwingUtilities.layoutCompoundLabel( b, fm, text, b.getIcon(),
|
|
||||||
b.getVerticalAlignment(), b.getHorizontalAlignment(),
|
|
||||||
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
|
|
||||||
viewR, iconR, textR,
|
|
||||||
(text != null) ? b.getIconTextGap() : 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Rectangle viewR = new Rectangle();
|
|
||||||
private static Rectangle textR = new Rectangle();
|
|
||||||
private static Rectangle iconR = new Rectangle();
|
|
||||||
|
|
||||||
//---- class FlatButtonListener -------------------------------------------
|
//---- class FlatButtonListener -------------------------------------------
|
||||||
|
|
||||||
protected class FlatButtonListener
|
protected class FlatButtonListener
|
||||||
|
|||||||
@@ -926,7 +926,7 @@ public class FlatComboBoxUI
|
|||||||
protected void configurePopup() {
|
protected void configurePopup() {
|
||||||
super.configurePopup();
|
super.configurePopup();
|
||||||
|
|
||||||
// make opaque to avoid that background shines through border (e.g. at 150% scaling)
|
// make opaque to avoid that background shines thru border (e.g. at 150% scaling)
|
||||||
setOpaque( true );
|
setOpaque( true );
|
||||||
|
|
||||||
// set popup border
|
// set popup border
|
||||||
@@ -944,7 +944,7 @@ public class FlatComboBoxUI
|
|||||||
if( popupBackground != null )
|
if( popupBackground != null )
|
||||||
list.setBackground( popupBackground );
|
list.setBackground( popupBackground );
|
||||||
|
|
||||||
// set popup background because it may shine through when scaled (e.g. at 150%)
|
// set popup background because it may shine thru when scaled (e.g. at 150%)
|
||||||
// use non-UIResource to avoid that it is overwritten when making
|
// use non-UIResource to avoid that it is overwritten when making
|
||||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||||
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
||||||
@@ -1090,7 +1090,7 @@ public class FlatComboBoxUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// using synchronized to avoid problems with code that modifies combo box
|
// using synchronized to avoid problems with code that modifies combo box
|
||||||
// (model, selection, etc.) not on AWT thread (which should be not done)
|
// (model, selection, etc) not on AWT thread (which should be not done)
|
||||||
synchronized void install( Component c, int focusWidth ) {
|
synchronized void install( Component c, int focusWidth ) {
|
||||||
if( !(c instanceof JComponent) )
|
if( !(c instanceof JComponent) )
|
||||||
return;
|
return;
|
||||||
@@ -1242,7 +1242,7 @@ public class FlatComboBoxUI
|
|||||||
* Key selection manager that delegates to the default manager.
|
* Key selection manager that delegates to the default manager.
|
||||||
* Shows the popup if Space key is pressed and "typed characters" buffer is empty.
|
* Shows the popup if Space key is pressed and "typed characters" buffer is empty.
|
||||||
* If items contain spaces (e.g. "a b") it is still possible to select them
|
* If items contain spaces (e.g. "a b") it is still possible to select them
|
||||||
* by pressing keys 'a', 'Space' and 'b'.
|
* by pressing keys a, Space and b.
|
||||||
*/
|
*/
|
||||||
private class FlatKeySelectionManager
|
private class FlatKeySelectionManager
|
||||||
implements JComboBox.KeySelectionManager, UIResource
|
implements JComboBox.KeySelectionManager, UIResource
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
||||||
import javax.swing.text.Caret;
|
import javax.swing.text.Caret;
|
||||||
|
import javax.swing.text.DefaultEditorKit;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
@@ -145,6 +146,21 @@ public class FlatEditorPaneUI
|
|||||||
focusListener = null;
|
focusListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installKeyboardActions() {
|
||||||
|
super.installKeyboardActions();
|
||||||
|
installKeyboardActions( getComponent() );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void installKeyboardActions( JTextComponent c ) {
|
||||||
|
FlatScrollPaneUI.installSmoothScrollingDelegateActions( c, false,
|
||||||
|
/* page-down */ DefaultEditorKit.pageDownAction, // PAGE_DOWN
|
||||||
|
/* page-up */ DefaultEditorKit.pageUpAction, // PAGE_UP
|
||||||
|
/* DefaultEditorKit.selectionPageDownAction */ "selection-page-down", // shift PAGE_DOWN
|
||||||
|
/* DefaultEditorKit.selectionPageUpAction */ "selection-page-up" // shift PAGE_UP
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Caret createCaret() {
|
protected Caret createCaret() {
|
||||||
return new FlatCaret( null, false );
|
return new FlatCaret( null, false );
|
||||||
@@ -159,6 +175,11 @@ public class FlatEditorPaneUI
|
|||||||
|
|
||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
propertyChange( getComponent(), e, this::installStyle );
|
propertyChange( getComponent(), e, this::installStyle );
|
||||||
|
|
||||||
|
// BasicEditorPaneUI.propertyChange() re-applied actions from editor kit,
|
||||||
|
// which removed our delegate actions
|
||||||
|
if( "editorKit".equals( propertyName ) )
|
||||||
|
installKeyboardActions( getComponent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e, Runnable installStyle ) {
|
static void propertyChange( JTextComponent c, PropertyChangeEvent e, Runnable installStyle ) {
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import java.beans.PropertyChangeEvent;
|
|||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
@@ -370,11 +369,7 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
// get system icon
|
// get system icon
|
||||||
if( f != null ) {
|
if( f != null ) {
|
||||||
try {
|
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
||||||
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
|
||||||
} catch( NullPointerException ex ) {
|
|
||||||
// Java 21 may throw a NPE for exe files that use default Windows exe icon
|
|
||||||
}
|
|
||||||
|
|
||||||
if( icon != null ) {
|
if( icon != null ) {
|
||||||
if( icon instanceof ImageIcon )
|
if( icon instanceof ImageIcon )
|
||||||
@@ -413,7 +408,7 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
protected final File[] files;
|
protected final File[] files;
|
||||||
protected final JToggleButton[] buttons;
|
protected final JToggleButton[] buttons;
|
||||||
protected final ButtonGroup buttonGroup = new ButtonGroup();
|
protected final ButtonGroup buttonGroup;
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
public FlatShortcutsPanel( JFileChooser fc ) {
|
public FlatShortcutsPanel( JFileChooser fc ) {
|
||||||
@@ -432,22 +427,19 @@ public class FlatFileChooserUI
|
|||||||
File[] files = getChooserShortcutPanelFiles( fsv );
|
File[] files = getChooserShortcutPanelFiles( fsv );
|
||||||
if( filesFunction != null )
|
if( filesFunction != null )
|
||||||
files = filesFunction.apply( files );
|
files = filesFunction.apply( files );
|
||||||
|
this.files = files;
|
||||||
|
|
||||||
// create toolbar buttons
|
// create toolbar buttons
|
||||||
ArrayList<File> filesList = new ArrayList<>();
|
buttons = new JToggleButton[files.length];
|
||||||
ArrayList<JToggleButton> buttonsList = new ArrayList<>();
|
buttonGroup = new ButtonGroup();
|
||||||
for( File file : files ) {
|
for( int i = 0; i < files.length; i++ ) {
|
||||||
if( file == null )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// wrap drive path
|
// wrap drive path
|
||||||
if( fsv.isFileSystemRoot( file ) )
|
if( fsv.isFileSystemRoot( files[i] ) )
|
||||||
file = fsv.createFileObject( file.getAbsolutePath() );
|
files[i] = fsv.createFileObject( files[i].getAbsolutePath() );
|
||||||
|
|
||||||
|
File file = files[i];
|
||||||
String name = getDisplayName( fsv, file );
|
String name = getDisplayName( fsv, file );
|
||||||
Icon icon = getIcon( fsv, file );
|
Icon icon = getIcon( fsv, file );
|
||||||
if( name == null )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// remove path from name
|
// remove path from name
|
||||||
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
||||||
@@ -462,21 +454,15 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
// create button
|
// create button
|
||||||
JToggleButton button = createButton( name, icon );
|
JToggleButton button = createButton( name, icon );
|
||||||
File f = file;
|
|
||||||
button.addActionListener( e -> {
|
button.addActionListener( e -> {
|
||||||
fc.setCurrentDirectory( f );
|
fc.setCurrentDirectory( file );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
add( button );
|
add( button );
|
||||||
buttonGroup.add( button );
|
buttonGroup.add( button );
|
||||||
|
buttons[i] = button;
|
||||||
filesList.add( file );
|
|
||||||
buttonsList.add( button );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.files = filesList.toArray( new File[filesList.size()] );
|
|
||||||
this.buttons = buttonsList.toArray( new JToggleButton[buttonsList.size()] );
|
|
||||||
|
|
||||||
directoryChanged( fc.getCurrentDirectory() );
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,36 +530,29 @@ public class FlatFileChooserUI
|
|||||||
if( doNotUseSystemIcons() )
|
if( doNotUseSystemIcons() )
|
||||||
return new FlatFileViewDirectoryIcon();
|
return new FlatFileViewDirectoryIcon();
|
||||||
|
|
||||||
|
// Java 17+ supports getting larger system icons
|
||||||
try {
|
try {
|
||||||
// Java 17+ supports getting larger system icons
|
if( SystemInfo.isJava_17_orLater ) {
|
||||||
try {
|
Method m = fsv.getClass().getMethod( "getSystemIcon", File.class, int.class, int.class );
|
||||||
if( SystemInfo.isJava_17_orLater ) {
|
return (Icon) m.invoke( fsv, file, iconSize.width, iconSize.height );
|
||||||
Method m = fsv.getClass().getMethod( "getSystemIcon", File.class, int.class, int.class );
|
} else if( iconSize.width > 16 || iconSize.height > 16 ) {
|
||||||
return (Icon) m.invoke( fsv, file, iconSize.width, iconSize.height );
|
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||||
} else if( iconSize.width > 16 || iconSize.height > 16 ) {
|
if( cls.isInstance( file ) ) {
|
||||||
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
Method m = file.getClass().getMethod( "getIcon", boolean.class );
|
||||||
if( cls.isInstance( file ) ) {
|
m.setAccessible( true );
|
||||||
Method m = file.getClass().getMethod( "getIcon", boolean.class );
|
Image image = (Image) m.invoke( file, true );
|
||||||
m.setAccessible( true );
|
if( image != null )
|
||||||
Image image = (Image) m.invoke( file, true );
|
return new ImageIcon( image );
|
||||||
if( image != null )
|
|
||||||
return new ImageIcon( image );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch( Exception ex ) {
|
|
||||||
// do not log InaccessibleObjectException because access
|
|
||||||
// may be denied via VM option '--illegal-access=deny' (default in Java 16)
|
|
||||||
// (not catching InaccessibleObjectException here because it is new in Java 9, but FlatLaf also runs on Java 8)
|
|
||||||
if( !"java.lang.reflect.InaccessibleObjectException".equals( ex.getClass().getName() ) )
|
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
|
||||||
}
|
}
|
||||||
|
} catch( IllegalAccessException ex ) {
|
||||||
// get system icon in default size 16x16
|
// do not log because access may be denied via VM option '--illegal-access=deny'
|
||||||
return fsv.getSystemIcon( file );
|
} catch( Exception ex ) {
|
||||||
} catch( NullPointerException ex ) {
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
// Java 21 may throw a NPE for exe files that use default Windows exe icon
|
|
||||||
return new FlatFileViewDirectoryIcon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get system icon in default size 16x16
|
||||||
|
return fsv.getSystemIcon( file );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void directoryChanged( File file ) {
|
protected void directoryChanged( File file ) {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import java.awt.Component;
|
|||||||
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 javax.swing.JComponent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line border for various components.
|
* Line border for various components.
|
||||||
@@ -67,9 +66,6 @@ public class FlatLineBorder
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
if( c instanceof JComponent && ((JComponent)c).getClientProperty( FlatPopupFactory.KEY_POPUP_USES_NATIVE_BORDER ) != null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ public class FlatListUI
|
|||||||
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
||||||
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
||||||
|
|
||||||
// special handling for the case that last column contains fewer cells than the other columns
|
// special handling for the case that last column contains less cells than the other columns
|
||||||
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
||||||
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
||||||
leftIndex = -1;
|
leftIndex = -1;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import java.awt.event.ActionEvent;
|
|||||||
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.AbstractAction;
|
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -149,7 +148,7 @@ public class FlatMenuBarUI
|
|||||||
map = new ActionMapUIResource();
|
map = new ActionMapUIResource();
|
||||||
SwingUtilities.replaceUIActionMap( menuBar, map );
|
SwingUtilities.replaceUIActionMap( menuBar, map );
|
||||||
}
|
}
|
||||||
map.put( "takeFocus", new TakeFocus() );
|
map.put( "takeFocus", new TakeFocus( "takeFocus" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
@@ -373,8 +372,12 @@ public class FlatMenuBarUI
|
|||||||
* On other platforms, the popup of the first menu is shown.
|
* On other platforms, the popup of the first menu is shown.
|
||||||
*/
|
*/
|
||||||
private static class TakeFocus
|
private static class TakeFocus
|
||||||
extends AbstractAction
|
extends FlatUIAction
|
||||||
{
|
{
|
||||||
|
public TakeFocus( String name ) {
|
||||||
|
super( name );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed( ActionEvent e ) {
|
public void actionPerformed( ActionEvent e ) {
|
||||||
JMenuBar menuBar = (JMenuBar) e.getSource();
|
JMenuBar menuBar = (JMenuBar) e.getSource();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Container;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
@@ -272,7 +271,7 @@ public class FlatMenuUI
|
|||||||
if( !isHover() )
|
if( !isHover() )
|
||||||
selectionBackground = getStyleFromMenuBarUI( ui -> ui.selectionBackground, menuBarSelectionBackground, selectionBackground );
|
selectionBackground = getStyleFromMenuBarUI( ui -> ui.selectionBackground, menuBarSelectionBackground, selectionBackground );
|
||||||
|
|
||||||
Container menuBar = menuItem.getParent();
|
JMenuBar menuBar = (JMenuBar) menuItem.getParent();
|
||||||
JRootPane rootPane = SwingUtilities.getRootPane( menuBar );
|
JRootPane rootPane = SwingUtilities.getRootPane( menuBar );
|
||||||
if( rootPane != null && rootPane.getParent() instanceof Window &&
|
if( rootPane != null && rootPane.getParent() instanceof Window &&
|
||||||
rootPane.getJMenuBar() == menuBar &&
|
rootPane.getJMenuBar() == menuBar &&
|
||||||
@@ -322,17 +321,12 @@ public class FlatMenuUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue ) {
|
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> f, T defaultValue ) {
|
||||||
Container menuItemParent = menuItem.getParent();
|
MenuBarUI ui = ((JMenuBar)menuItem.getParent()).getUI();
|
||||||
if( menuItemParent instanceof JMenuBar ) {
|
if( !(ui instanceof FlatMenuBarUI) )
|
||||||
MenuBarUI ui = ((JMenuBar) menuItemParent).getUI();
|
return defaultValue;
|
||||||
if( ui instanceof FlatMenuBarUI ) {
|
|
||||||
T value = f.apply( (FlatMenuBarUI) ui );
|
T value = f.apply( (FlatMenuBarUI) ui );
|
||||||
if( value != null ) {
|
return (value != null) ? value : defaultValue;
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,15 +78,9 @@ class FlatNativeLibrary
|
|||||||
//
|
//
|
||||||
// To avoid this, flatlaf.dll is not linked to jawt.dll,
|
// To avoid this, flatlaf.dll is not linked to jawt.dll,
|
||||||
// which avoids loading jawt.dll when flatlaf.dll is loaded.
|
// which avoids loading jawt.dll when flatlaf.dll is loaded.
|
||||||
// Instead, flatlaf.dll dynamically loads jawt.dll when first used,
|
// Instead flatlaf.dll dynamically loads jawt.dll when first used,
|
||||||
// which is guaranteed after AWT initialization.
|
// which is guaranteed after AWT initialization.
|
||||||
|
|
||||||
} else if( SystemInfo.isMacOS_10_14_Mojave_orLater && (SystemInfo.isAARCH64 || SystemInfo.isX86_64) ) {
|
|
||||||
// macOS: requires macOS 10.14 or later (arm64 or x86_64)
|
|
||||||
|
|
||||||
classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64";
|
|
||||||
ext = "dylib";
|
|
||||||
|
|
||||||
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
||||||
// Linux: requires x86_64
|
// Linux: requires x86_64
|
||||||
|
|
||||||
@@ -117,32 +111,13 @@ class FlatNativeLibrary
|
|||||||
if( library.isLoaded() )
|
if( library.isLoaded() )
|
||||||
return library;
|
return library;
|
||||||
|
|
||||||
LoggingFacade.INSTANCE.logSevere( "Did not find library '" + System.mapLibraryName( libraryName )
|
LoggingFacade.INSTANCE.logSevere( "Did not find library " + libraryName + " in java.library.path, using extracted library instead", null );
|
||||||
+ "' in java.library.path '" + System.getProperty( "java.library.path" )
|
|
||||||
+ "', using extracted library instead", null );
|
|
||||||
} else {
|
} else {
|
||||||
// try standard library naming scheme
|
|
||||||
// (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives')
|
|
||||||
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
|
File libraryFile = new File( libraryPath, System.mapLibraryName( libraryName ) );
|
||||||
if( libraryFile.exists() )
|
if( libraryFile.exists() )
|
||||||
return new NativeLibrary( libraryFile, true );
|
return new NativeLibrary( libraryFile, true );
|
||||||
|
|
||||||
// try Maven naming scheme
|
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
|
||||||
// (see https://www.formdev.com/flatlaf/native-libraries/)
|
|
||||||
String libraryName2 = null;
|
|
||||||
File jarFile = getJarFile();
|
|
||||||
if( jarFile != null ) {
|
|
||||||
libraryName2 = buildLibraryName( jarFile, classifier, ext );
|
|
||||||
File libraryFile2 = new File( libraryPath, libraryName2 );
|
|
||||||
if( libraryFile2.exists() )
|
|
||||||
return new NativeLibrary( libraryFile2, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggingFacade.INSTANCE.logSevere( "Did not find library '"
|
|
||||||
+ libraryFile.getName()
|
|
||||||
+ (libraryName2 != null ? ("' or '" + libraryName2) : "")
|
|
||||||
+ "' in '" + libraryFile.getParentFile().getAbsolutePath()
|
|
||||||
+ "', using extracted library instead", null );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,33 +145,6 @@ class FlatNativeLibrary
|
|||||||
* flatlaf-3.1-linux-x86_64.so
|
* flatlaf-3.1-linux-x86_64.so
|
||||||
*/
|
*/
|
||||||
private static File findLibraryBesideJar( String classifier, String ext ) {
|
private static File findLibraryBesideJar( String classifier, String ext ) {
|
||||||
// get location of FlatLaf jar (or fat/uber application jar)
|
|
||||||
File jarFile = getJarFile();
|
|
||||||
if( jarFile == null )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// build library file
|
|
||||||
String libraryName = buildLibraryName( jarFile, classifier, ext );
|
|
||||||
File parent = jarFile.getParentFile();
|
|
||||||
|
|
||||||
// check whether native library exists in same directory as jar
|
|
||||||
File libraryFile = new File( parent, libraryName );
|
|
||||||
if( libraryFile.isFile() )
|
|
||||||
return libraryFile;
|
|
||||||
|
|
||||||
// if jar is in "lib" directory, then also check whether native library exists
|
|
||||||
// in "../bin" directory
|
|
||||||
if( parent.getName().equalsIgnoreCase( "lib" ) ) {
|
|
||||||
libraryFile = new File( parent.getParentFile(), "bin/" + libraryName );
|
|
||||||
if( libraryFile.isFile() )
|
|
||||||
return libraryFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
// native library not found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File getJarFile() {
|
|
||||||
try {
|
try {
|
||||||
// get location of FlatLaf jar
|
// get location of FlatLaf jar
|
||||||
CodeSource codeSource = FlatNativeLibrary.class.getProtectionDomain().getCodeSource();
|
CodeSource codeSource = FlatNativeLibrary.class.getProtectionDomain().getCodeSource();
|
||||||
@@ -214,19 +162,31 @@ class FlatNativeLibrary
|
|||||||
if( !jarFile.isFile() )
|
if( !jarFile.isFile() )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return jarFile;
|
// build library file
|
||||||
|
String jarName = jarFile.getName();
|
||||||
|
String jarBasename = jarName.substring( 0, jarName.lastIndexOf( '.' ) );
|
||||||
|
File parent = jarFile.getParentFile();
|
||||||
|
String libraryName = jarBasename
|
||||||
|
+ (jarBasename.contains( "flatlaf" ) ? "" : "-flatlaf")
|
||||||
|
+ '-' + classifier + '.' + ext;
|
||||||
|
|
||||||
|
// check whether native library exists in same directory as jar
|
||||||
|
File libraryFile = new File( parent, libraryName );
|
||||||
|
if( libraryFile.isFile() )
|
||||||
|
return libraryFile;
|
||||||
|
|
||||||
|
// if jar is in "lib" directory, then also check whether library exists
|
||||||
|
// in "../bin" directory
|
||||||
|
if( parent.getName().equalsIgnoreCase( "lib" ) ) {
|
||||||
|
libraryFile = new File( parent.getParentFile(), "bin/" + libraryName );
|
||||||
|
if( libraryFile.isFile() )
|
||||||
|
return libraryFile;
|
||||||
|
}
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
|
LoggingFacade.INSTANCE.logSevere( ex.getMessage(), ex );
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static String buildLibraryName( File jarFile, String classifier, String ext ) {
|
return null;
|
||||||
String jarName = jarFile.getName();
|
|
||||||
String jarBasename = jarName.substring( 0, jarName.lastIndexOf( '.' ) );
|
|
||||||
return jarBasename
|
|
||||||
+ (jarBasename.contains( "flatlaf" ) ? "" : "-flatlaf")
|
|
||||||
+ '-' + classifier + '.' + ext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadJAWT() {
|
private static void loadJAWT() {
|
||||||
|
|||||||
@@ -35,12 +35,6 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
*/
|
*/
|
||||||
class FlatNativeLinuxLibrary
|
class FlatNativeLinuxLibrary
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Checks whether native library is loaded/available.
|
|
||||||
* <p>
|
|
||||||
* <b>Note</b>: It is required to invoke this method before invoking any other
|
|
||||||
* method of this class. Otherwise, the native library may not be loaded.
|
|
||||||
*/
|
|
||||||
static boolean isLoaded() {
|
static boolean isLoaded() {
|
||||||
return SystemInfo.isLinux && FlatNativeLibrary.isLoaded();
|
return SystemInfo.isLinux && FlatNativeLibrary.isLoaded();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 FormDev Software GmbH
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
|
||||||
|
|
||||||
import java.awt.Window;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Native methods for macOS.
|
|
||||||
* <p>
|
|
||||||
* <b>Note</b>: This is private API. Do not use!
|
|
||||||
*
|
|
||||||
* <h2>Methods that use windows as parameter</h2>
|
|
||||||
*
|
|
||||||
* For all methods that accept a {@link java.awt.Window} as parameter,
|
|
||||||
* the underlying macOS window must be already created,
|
|
||||||
* otherwise the method fails. You can use following to ensure this:
|
|
||||||
* <pre>{@code
|
|
||||||
* if( !window.isDisplayable() )
|
|
||||||
* window.addNotify();
|
|
||||||
* }</pre>
|
|
||||||
* or invoke the method after packing the window. E.g.
|
|
||||||
* <pre>{@code
|
|
||||||
* window.pack();
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @author Karl Tauber
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public class FlatNativeMacLibrary
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Checks whether native library is loaded/available.
|
|
||||||
* <p>
|
|
||||||
* <b>Note</b>: It is required to invoke this method before invoking any other
|
|
||||||
* method of this class. Otherwise, the native library may not be loaded.
|
|
||||||
*/
|
|
||||||
public static boolean isLoaded() {
|
|
||||||
return FlatNativeLibrary.isLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
public native static boolean setWindowRoundedBorder( Window window, float radius, float borderWidth, int borderColor );
|
|
||||||
}
|
|
||||||
@@ -17,26 +17,20 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Graphics;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JRootPane;
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import javax.swing.plaf.BorderUIResource;
|
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.FlatSystemProperties;
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,15 +54,27 @@ public class FlatNativeWindowBorder
|
|||||||
!SystemInfo.isWinPE &&
|
!SystemInfo.isWinPE &&
|
||||||
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_WINDOW_DECORATIONS, true );
|
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_WINDOW_DECORATIONS, true );
|
||||||
|
|
||||||
|
// check this field before using class JBRCustomDecorations to avoid unnecessary loading of that class
|
||||||
|
private static final boolean canUseJBRCustomDecorations =
|
||||||
|
canUseWindowDecorations &&
|
||||||
|
SystemInfo.isJetBrainsJVM_11_orLater &&
|
||||||
|
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, false );
|
||||||
|
|
||||||
private static Boolean supported;
|
private static Boolean supported;
|
||||||
private static Provider nativeProvider;
|
private static Provider nativeProvider;
|
||||||
|
|
||||||
public static boolean isSupported() {
|
public static boolean isSupported() {
|
||||||
|
if( canUseJBRCustomDecorations )
|
||||||
|
return JBRCustomDecorations.isSupported();
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object install( JRootPane rootPane ) {
|
static Object install( JRootPane rootPane ) {
|
||||||
|
if( canUseJBRCustomDecorations )
|
||||||
|
return JBRCustomDecorations.install( rootPane );
|
||||||
|
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -157,6 +163,11 @@ public class FlatNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void uninstall( JRootPane rootPane, Object data ) {
|
static void uninstall( JRootPane rootPane, Object data ) {
|
||||||
|
if( canUseJBRCustomDecorations ) {
|
||||||
|
JBRCustomDecorations.uninstall( rootPane, data );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -204,6 +215,9 @@ public class FlatNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasCustomDecoration( Window window ) {
|
public static boolean hasCustomDecoration( Window window ) {
|
||||||
|
if( canUseJBRCustomDecorations )
|
||||||
|
return JBRCustomDecorations.hasCustomDecoration( window );
|
||||||
|
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -211,6 +225,11 @@ public class FlatNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setHasCustomDecoration( Window window, boolean hasCustomDecoration ) {
|
public static void setHasCustomDecoration( Window window, boolean hasCustomDecoration ) {
|
||||||
|
if( canUseJBRCustomDecorations ) {
|
||||||
|
JBRCustomDecorations.setHasCustomDecoration( window, hasCustomDecoration );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -221,6 +240,11 @@ public class FlatNativeWindowBorder
|
|||||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
List<Rectangle> hitTestSpots, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||||
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
||||||
{
|
{
|
||||||
|
if( canUseJBRCustomDecorations ) {
|
||||||
|
JBRCustomDecorations.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -229,7 +253,7 @@ public class FlatNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean showWindow( Window window, int cmd ) {
|
static boolean showWindow( Window window, int cmd ) {
|
||||||
if( !isSupported() )
|
if( canUseJBRCustomDecorations || !isSupported() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return nativeProvider.showWindow( window, cmd );
|
return nativeProvider.showWindow( window, cmd );
|
||||||
@@ -296,36 +320,20 @@ public class FlatNativeWindowBorder
|
|||||||
* No longer needed since Windows 11.
|
* No longer needed since Windows 11.
|
||||||
*/
|
*/
|
||||||
static class WindowTopBorder
|
static class WindowTopBorder
|
||||||
extends BorderUIResource.EmptyBorderUIResource
|
extends JBRCustomDecorations.JBRWindowTopBorder
|
||||||
{
|
{
|
||||||
private static WindowTopBorder instance;
|
private static WindowTopBorder instance;
|
||||||
|
|
||||||
private final Color activeLightColor = new Color( 0x707070 );
|
static JBRWindowTopBorder getInstance() {
|
||||||
private final Color activeDarkColor = new Color( 0x2D2E2F );
|
if( canUseJBRCustomDecorations )
|
||||||
private final Color inactiveLightColor = new Color( 0xaaaaaa );
|
return JBRWindowTopBorder.getInstance();
|
||||||
private final Color inactiveDarkColor = new Color( 0x494A4B );
|
|
||||||
|
|
||||||
private boolean colorizationAffectsBorders;
|
|
||||||
private Color activeColor;
|
|
||||||
|
|
||||||
static WindowTopBorder getInstance() {
|
|
||||||
if( instance == null )
|
if( instance == null )
|
||||||
instance = new WindowTopBorder();
|
instance = new WindowTopBorder();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowTopBorder() {
|
@Override
|
||||||
super( 1, 0, 0, 0 );
|
|
||||||
|
|
||||||
update();
|
|
||||||
installListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
colorizationAffectsBorders = isColorizationColorAffectsBorders();
|
|
||||||
activeColor = calculateActiveBorderColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void installListeners() {
|
void installListeners() {
|
||||||
nativeProvider.addChangeListener( e -> {
|
nativeProvider.addChangeListener( e -> {
|
||||||
update();
|
update();
|
||||||
@@ -338,69 +346,19 @@ public class FlatNativeWindowBorder
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
boolean isColorizationColorAffectsBorders() {
|
boolean isColorizationColorAffectsBorders() {
|
||||||
return nativeProvider.isColorizationColorAffectsBorders();
|
return nativeProvider.isColorizationColorAffectsBorders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
Color getColorizationColor() {
|
Color getColorizationColor() {
|
||||||
return nativeProvider.getColorizationColor();
|
return nativeProvider.getColorizationColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
int getColorizationColorBalance() {
|
int getColorizationColorBalance() {
|
||||||
return nativeProvider.getColorizationColorBalance();
|
return nativeProvider.getColorizationColorBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color calculateActiveBorderColor() {
|
|
||||||
if( !colorizationAffectsBorders )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Color colorizationColor = getColorizationColor();
|
|
||||||
if( colorizationColor != null ) {
|
|
||||||
int colorizationColorBalance = getColorizationColorBalance();
|
|
||||||
if( colorizationColorBalance < 0 || colorizationColorBalance > 100 )
|
|
||||||
colorizationColorBalance = 100;
|
|
||||||
|
|
||||||
if( colorizationColorBalance == 0 )
|
|
||||||
return new Color( 0xD9D9D9 );
|
|
||||||
if( colorizationColorBalance == 100 )
|
|
||||||
return colorizationColor;
|
|
||||||
|
|
||||||
float alpha = colorizationColorBalance / 100.0f;
|
|
||||||
float remainder = 1 - alpha;
|
|
||||||
int r = Math.round( colorizationColor.getRed() * alpha + 0xD9 * remainder );
|
|
||||||
int g = Math.round( colorizationColor.getGreen() * alpha + 0xD9 * remainder );
|
|
||||||
int b = Math.round( colorizationColor.getBlue() * alpha + 0xD9 * remainder );
|
|
||||||
|
|
||||||
// avoid potential IllegalArgumentException in Color constructor
|
|
||||||
r = Math.min( Math.max( r, 0 ), 255 );
|
|
||||||
g = Math.min( Math.max( g, 0 ), 255 );
|
|
||||||
b = Math.min( Math.max( b, 0 ), 255 );
|
|
||||||
|
|
||||||
return new Color( r, g, b );
|
|
||||||
}
|
|
||||||
|
|
||||||
Color activeBorderColor = (Color) Toolkit.getDefaultToolkit().getDesktopProperty( "win.frame.activeBorderColor" );
|
|
||||||
return (activeBorderColor != null) ? activeBorderColor : UIManager.getColor( "MenuBar.borderColor" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
|
||||||
Window window = SwingUtilities.windowForComponent( c );
|
|
||||||
boolean active = window != null && window.isActive();
|
|
||||||
boolean dark = FlatLaf.isLafDark();
|
|
||||||
|
|
||||||
g.setColor( active
|
|
||||||
? (activeColor != null ? activeColor : (dark ? activeDarkColor : activeLightColor))
|
|
||||||
: (dark ? inactiveDarkColor : inactiveLightColor) );
|
|
||||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
|
||||||
g.fillRect( x, y, width, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void repaintBorder( Component c ) {
|
|
||||||
c.repaint( 0, 0, c.getWidth(), 1 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
@@ -32,12 +31,6 @@ public class FlatNativeWindowsLibrary
|
|||||||
{
|
{
|
||||||
private static long osBuildNumber = Long.MIN_VALUE;
|
private static long osBuildNumber = Long.MIN_VALUE;
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether native library is loaded/available.
|
|
||||||
* <p>
|
|
||||||
* <b>Note</b>: It is required to invoke this method before invoking any other
|
|
||||||
* method of this class. Otherwise, the native library may not be loaded.
|
|
||||||
*/
|
|
||||||
public static boolean isLoaded() {
|
public static boolean isLoaded() {
|
||||||
return SystemInfo.isWindows && FlatNativeLibrary.isLoaded();
|
return SystemInfo.isWindows && FlatNativeLibrary.isLoaded();
|
||||||
}
|
}
|
||||||
@@ -100,60 +93,15 @@ public class FlatNativeWindowsLibrary
|
|||||||
public native static boolean setWindowCornerPreference( long hwnd, int cornerPreference );
|
public native static boolean setWindowCornerPreference( long hwnd, int cornerPreference );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DWMWINDOWATTRIBUTE
|
* Sets the color of the window border.
|
||||||
* see https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
* The red/green/blue values must be in range {@code 0 - 255}.
|
||||||
*
|
* If red is {@code -1}, then the system default border color is used (useful to reset the border color).
|
||||||
* @since 3.3
|
* If red is {@code -2}, then no border is painted.
|
||||||
*/
|
* <p>
|
||||||
public static final int
|
* Invokes Win32 API method {@code DwmSetWindowAttribute(DWMWA_BORDER_COLOR)}.
|
||||||
DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
|
|
||||||
DWMWA_BORDER_COLOR = 34,
|
|
||||||
DWMWA_CAPTION_COLOR = 35,
|
|
||||||
DWMWA_TEXT_COLOR = 36;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code BOOL} attribute value.
|
|
||||||
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public native static boolean dwmSetWindowAttributeBOOL( long hwnd, int attribute, boolean value );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code DWORD} attribute value.
|
|
||||||
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public native static boolean dwmSetWindowAttributeDWORD( long hwnd, int attribute, int value );
|
|
||||||
|
|
||||||
/** @since 3.3 */
|
|
||||||
public static final int
|
|
||||||
// use this constant to reset any window part colors to the system default behavior
|
|
||||||
DWMWA_COLOR_DEFAULT = 0xFFFFFFFF,
|
|
||||||
// use this constant to specify that a window part should not be rendered
|
|
||||||
DWMWA_COLOR_NONE = 0xFFFFFFFE;
|
|
||||||
|
|
||||||
/** @since 3.3 */
|
|
||||||
public static final Color COLOR_NONE = new Color( 0, true );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes Win32 API method {@code DwmSetWindowAttribute()} with a {@code COLORREF} attribute value.
|
|
||||||
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
* See https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmsetwindowattribute
|
||||||
* <p>
|
* <p>
|
||||||
* Supported since Windows 11 Build 22000.
|
* Supported since Windows 11 Build 22000.
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
*/
|
||||||
public static boolean dwmSetWindowAttributeCOLORREF( long hwnd, int attribute, Color color ) {
|
public native static boolean setWindowBorderColor( long hwnd, int red, int green, int blue );
|
||||||
// convert color to Windows RGB value
|
|
||||||
int rgb = (color == COLOR_NONE)
|
|
||||||
? DWMWA_COLOR_NONE
|
|
||||||
: (color != null
|
|
||||||
? (color.getRed() | (color.getGreen() << 8) | (color.getBlue() << 16))
|
|
||||||
: DWMWA_COLOR_DEFAULT);
|
|
||||||
|
|
||||||
// DwmSetWindowAttribute() expects COLORREF as attribute value, which is defined as DWORD
|
|
||||||
return dwmSetWindowAttributeDWORD( hwnd, attribute, rgb );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JRootPane;
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
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;
|
||||||
@@ -113,6 +115,13 @@ public class FlatOptionPaneUI
|
|||||||
sameSizeButtons = FlatUIUtils.getUIBoolean( "OptionPane.sameSizeButtons", true );
|
sameSizeButtons = FlatUIUtils.getUIBoolean( "OptionPane.sameSizeButtons", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents() {
|
||||||
|
super.installComponents();
|
||||||
|
|
||||||
|
updateChildPanels( optionPane );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener() {
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||||
@@ -146,13 +155,6 @@ public class FlatOptionPaneUI
|
|||||||
protected Container createMessageArea() {
|
protected Container createMessageArea() {
|
||||||
Container messageArea = super.createMessageArea();
|
Container messageArea = super.createMessageArea();
|
||||||
|
|
||||||
// use non-UIResource OptionPane.messageAreaBorder to avoid that it is replaced when switching LaF
|
|
||||||
// and make panel non-opaque for OptionPane.background
|
|
||||||
updateAreaPanel( messageArea );
|
|
||||||
|
|
||||||
// make known sub-panels non-opaque for OptionPane.background
|
|
||||||
updateKnownChildPanels( messageArea );
|
|
||||||
|
|
||||||
// set icon-message gap
|
// set icon-message gap
|
||||||
if( iconMessageGap > 0 ) {
|
if( iconMessageGap > 0 ) {
|
||||||
Component iconMessageSeparator = SwingUtils.getComponentByName( messageArea, "OptionPane.separator" );
|
Component iconMessageSeparator = SwingUtils.getComponentByName( messageArea, "OptionPane.separator" );
|
||||||
@@ -167,10 +169,6 @@ public class FlatOptionPaneUI
|
|||||||
protected Container createButtonArea() {
|
protected Container createButtonArea() {
|
||||||
Container buttonArea = super.createButtonArea();
|
Container buttonArea = super.createButtonArea();
|
||||||
|
|
||||||
// use non-UIResource OptionPane.buttonAreaBorder to avoid that it is replaced when switching LaF
|
|
||||||
// and make panel non-opaque for OptionPane.background
|
|
||||||
updateAreaPanel( buttonArea );
|
|
||||||
|
|
||||||
// scale button padding and subtract focusWidth
|
// scale button padding and subtract focusWidth
|
||||||
if( buttonArea.getLayout() instanceof ButtonAreaLayout ) {
|
if( buttonArea.getLayout() instanceof ButtonAreaLayout ) {
|
||||||
ButtonAreaLayout layout = (ButtonAreaLayout) buttonArea.getLayout();
|
ButtonAreaLayout layout = (ButtonAreaLayout) buttonArea.getLayout();
|
||||||
@@ -220,33 +218,22 @@ public class FlatOptionPaneUI
|
|||||||
super.addMessageComponents( container, cons, msg, maxll, internallyCreated );
|
super.addMessageComponents( container, cons, msg, maxll, internallyCreated );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAreaPanel( Container area ) {
|
private void updateChildPanels( Container c ) {
|
||||||
if( !(area instanceof JPanel) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// use non-UIResource border to avoid that it is replaced when switching LaF
|
|
||||||
// and make panel non-opaque for OptionPane.background
|
|
||||||
JPanel panel = (JPanel) area;
|
|
||||||
panel.setBorder( FlatUIUtils.nonUIResource( panel.getBorder() ) );
|
|
||||||
panel.setOpaque( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateKnownChildPanels( Container c ) {
|
|
||||||
for( Component child : c.getComponents() ) {
|
for( Component child : c.getComponents() ) {
|
||||||
if( child instanceof JPanel && child.getName() != null ) {
|
if( child.getClass() == JPanel.class ) {
|
||||||
switch( child.getName() ) {
|
JPanel panel = (JPanel)child;
|
||||||
case "OptionPane.realBody":
|
|
||||||
case "OptionPane.body":
|
// make sub-panel non-opaque for OptionPane.background
|
||||||
case "OptionPane.separator":
|
panel.setOpaque( false );
|
||||||
case "OptionPane.break":
|
|
||||||
// make known sub-panels non-opaque for OptionPane.background
|
// use non-UIResource borders to avoid that they are replaced when switching LaF
|
||||||
((JPanel)child).setOpaque( false );
|
Border border = panel.getBorder();
|
||||||
break;
|
if( border instanceof UIResource )
|
||||||
}
|
panel.setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( child instanceof Container )
|
if( child instanceof Container )
|
||||||
updateKnownChildPanels( (Container) child );
|
updateChildPanels( (Container) child );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ 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.awt.event.MouseEvent;
|
||||||
import java.awt.event.WindowFocusListener;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
@@ -71,8 +70,6 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
public class FlatPopupFactory
|
public class FlatPopupFactory
|
||||||
extends PopupFactory
|
extends PopupFactory
|
||||||
{
|
{
|
||||||
static final String KEY_POPUP_USES_NATIVE_BORDER = "FlatLaf.internal.FlatPopupFactory.popupUsesNativeBorder";
|
|
||||||
|
|
||||||
private MethodHandle java8getPopupMethod;
|
private MethodHandle java8getPopupMethod;
|
||||||
private MethodHandle java9getPopupMethod;
|
private MethodHandle java9getPopupMethod;
|
||||||
|
|
||||||
@@ -86,35 +83,26 @@ public class FlatPopupFactory
|
|||||||
y = pt.y;
|
y = pt.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixLinuxWaylandJava21focusIssue( owner );
|
|
||||||
|
|
||||||
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
|
boolean forceHeavyWeight = isOptionEnabled( owner, contents, FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, "Popup.forceHeavyWeight" );
|
||||||
|
|
||||||
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
|
if( !isOptionEnabled( owner, contents, FlatClientProperties.POPUP_DROP_SHADOW_PAINTED, "Popup.dropShadowPainted" ) || SystemInfo.isProjector || SystemInfo.isWebswing )
|
||||||
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), contents );
|
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), contents );
|
||||||
|
|
||||||
// macOS and Linux adds drop shadow to heavy weight popups
|
// macOS and Linux adds drop shadow to heavy weight popups
|
||||||
if( SystemInfo.isMacOS || SystemInfo.isLinux ) {
|
if( SystemInfo.isMacOS || SystemInfo.isLinux )
|
||||||
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
return new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
||||||
if( popup.popupWindow != null && SystemInfo.isMacOS && FlatNativeMacLibrary.isLoaded() )
|
|
||||||
setupRoundedBorder( popup.popupWindow, owner, contents );
|
|
||||||
return popup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows 11 with FlatLaf native library can use rounded corners and shows drop shadow for heavy weight popups
|
// Windows 11 with FlatLaf native library can use rounded corners and shows drop shadow for heavy weight popups
|
||||||
|
int borderCornerRadius;
|
||||||
if( isWindows11BorderSupported() &&
|
if( isWindows11BorderSupported() &&
|
||||||
getBorderCornerRadius( owner, contents ) > 0 )
|
(borderCornerRadius = getBorderCornerRadius( owner, contents )) > 0 )
|
||||||
{
|
{
|
||||||
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), contents );
|
||||||
if( popup.popupWindow != null )
|
if( popup.popupWindow != null )
|
||||||
setupRoundedBorder( popup.popupWindow, owner, contents );
|
setupWindows11Border( popup.popupWindow, contents, borderCornerRadius );
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether popup overlaps a heavy weight component
|
|
||||||
if( !forceHeavyWeight && overlapsHeavyWeightComponent( owner, contents, x, y ) )
|
|
||||||
forceHeavyWeight = true;
|
|
||||||
|
|
||||||
// create drop shadow popup
|
// create drop shadow popup
|
||||||
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
return new DropShadowPopup( getPopupForScreenOfOwner( owner, contents, x, y, forceHeavyWeight ), owner, contents );
|
||||||
}
|
}
|
||||||
@@ -167,6 +155,67 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the given popup and, if necessary, fixes the location of a heavy weight popup window.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* E.g. when opening a dialog on the secondary screen and making combobox popup visible.
|
||||||
|
* <p>
|
||||||
|
* This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8224608
|
||||||
|
*/
|
||||||
|
private static void showPopupAndFixLocation( Popup popup, Window popupWindow ) {
|
||||||
|
if( popupWindow != null ) {
|
||||||
|
// remember location of heavy weight popup window
|
||||||
|
int x = popupWindow.getX();
|
||||||
|
int y = popupWindow.getY();
|
||||||
|
|
||||||
|
popup.show();
|
||||||
|
|
||||||
|
// restore popup window location if it has changed
|
||||||
|
// (probably scaled when screens use different scale factors)
|
||||||
|
if( popupWindow.getX() != x || popupWindow.getY() != y )
|
||||||
|
popupWindow.setLocation( x, y );
|
||||||
|
} else
|
||||||
|
popup.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOptionEnabled( Component owner, Component contents, String clientKey, String uiKey ) {
|
||||||
|
Object value = getOption( owner, contents, clientKey, uiKey );
|
||||||
|
return (value instanceof Boolean) ? (Boolean) value : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getBorderCornerRadius( Component owner, Component contents ) {
|
||||||
|
String uiKey =
|
||||||
|
(contents instanceof BasicComboPopup) ? "ComboBox.borderCornerRadius" :
|
||||||
|
(contents instanceof JPopupMenu) ? "PopupMenu.borderCornerRadius" :
|
||||||
|
(contents instanceof JToolTip) ? "ToolTip.borderCornerRadius" :
|
||||||
|
"Popup.borderCornerRadius";
|
||||||
|
|
||||||
|
Object value = getOption( owner, contents, FlatClientProperties.POPUP_BORDER_CORNER_RADIUS, uiKey );
|
||||||
|
return (value instanceof Integer) ? (Integer) value : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get option from:
|
||||||
|
* <ol>
|
||||||
|
* <li>client property {@code clientKey} of {@code owner}
|
||||||
|
* <li>client property {@code clientKey} of {@code contents}
|
||||||
|
* <li>UI property {@code uiKey}
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
private Object getOption( Component owner, Component contents, String clientKey, String uiKey ) {
|
||||||
|
for( Component c : new Component[] { owner, contents } ) {
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Object value = ((JComponent)c).getClientProperty( clientKey );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UIManager.get( uiKey );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There is no API in Java 8 to force creation of heavy weight popups,
|
* There is no API in Java 8 to force creation of heavy weight popups,
|
||||||
* but it is possible with reflection. Java 9 provides a new method.
|
* but it is possible with reflection. Java 9 provides a new method.
|
||||||
@@ -202,33 +251,6 @@ public class FlatPopupFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOptionEnabled( Component owner, Component contents, String clientKey, String uiKey ) {
|
|
||||||
Object value = getOption( owner, contents, clientKey, uiKey );
|
|
||||||
return (value instanceof Boolean) ? (Boolean) value : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get option from:
|
|
||||||
* <ol>
|
|
||||||
* <li>client property {@code clientKey} of {@code owner}
|
|
||||||
* <li>client property {@code clientKey} of {@code contents}
|
|
||||||
* <li>UI property {@code uiKey}
|
|
||||||
* </ol>
|
|
||||||
*/
|
|
||||||
private static Object getOption( Component owner, Component contents, String clientKey, String uiKey ) {
|
|
||||||
for( Component c : new Component[] { owner, contents } ) {
|
|
||||||
if( c instanceof JComponent ) {
|
|
||||||
Object value = ((JComponent)c).getClientProperty( clientKey );
|
|
||||||
if( value != null )
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return UIManager.get( uiKey );
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- tooltips -----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usually ToolTipManager places a tooltip at (mouseLocation.x, mouseLocation.y + 20).
|
* Usually ToolTipManager places a tooltip at (mouseLocation.x, mouseLocation.y + 20).
|
||||||
* In case that the tooltip would be partly outside of the screen,
|
* In case that the tooltip would be partly outside of the screen,
|
||||||
@@ -313,58 +335,48 @@ public class FlatPopupFactory
|
|||||||
((JComponent)owner).getToolTipLocation( me ) != null;
|
((JComponent)owner).getToolTipLocation( me ) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- native rounded border ----------------------------------------------
|
|
||||||
|
|
||||||
private static boolean isWindows11BorderSupported() {
|
private static boolean isWindows11BorderSupported() {
|
||||||
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded();
|
return SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) {
|
private static void setupWindows11Border( Window popupWindow, Component contents, int borderCornerRadius ) {
|
||||||
// make sure that the native window is created
|
// make sure that the Windows 11 window is created
|
||||||
if( !popupWindow.isDisplayable() )
|
if( !popupWindow.isDisplayable() )
|
||||||
popupWindow.addNotify();
|
popupWindow.addNotify();
|
||||||
|
|
||||||
int borderCornerRadius = getBorderCornerRadius( owner, contents );
|
// get window handle
|
||||||
float borderWidth = getRoundedBorderWidth( owner, contents );
|
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
||||||
|
|
||||||
// get Swing border color
|
// set corner preference
|
||||||
Color borderColor = null; // use system default color
|
int cornerPreference = (borderCornerRadius <= 4)
|
||||||
|
? FlatNativeWindowsLibrary.DWMWCP_ROUNDSMALL // 4px
|
||||||
|
: FlatNativeWindowsLibrary.DWMWCP_ROUND; // 8px
|
||||||
|
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, cornerPreference );
|
||||||
|
|
||||||
|
// set border color
|
||||||
|
int red = -1; // use system default color
|
||||||
|
int green = 0;
|
||||||
|
int blue = 0;
|
||||||
if( contents instanceof JComponent ) {
|
if( contents instanceof JComponent ) {
|
||||||
Border border = ((JComponent)contents).getBorder();
|
Border border = ((JComponent)contents).getBorder();
|
||||||
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
|
border = FlatUIUtils.unwrapNonUIResourceBorder( border );
|
||||||
|
|
||||||
// get color from border of contents (e.g. JPopupMenu or JToolTip)
|
// get color from border of contents (e.g. JPopupMenu or JToolTip)
|
||||||
|
Color borderColor = null;
|
||||||
if( border instanceof FlatLineBorder )
|
if( border instanceof FlatLineBorder )
|
||||||
borderColor = ((FlatLineBorder)border).getLineColor();
|
borderColor = ((FlatLineBorder)border).getLineColor();
|
||||||
else if( border instanceof LineBorder )
|
else if( border instanceof LineBorder )
|
||||||
borderColor = ((LineBorder)border).getLineColor();
|
borderColor = ((LineBorder)border).getLineColor();
|
||||||
else if( border instanceof EmptyBorder )
|
else if( border instanceof EmptyBorder )
|
||||||
borderColor = FlatNativeWindowsLibrary.COLOR_NONE; // do not paint border
|
red = -2; // do not paint border
|
||||||
|
|
||||||
// avoid that FlatLineBorder paints the Swing border
|
if( borderColor != null ) {
|
||||||
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, true );
|
red = borderColor.getRed();
|
||||||
}
|
green = borderColor.getGreen();
|
||||||
|
blue = borderColor.getBlue();
|
||||||
if( SystemInfo.isWindows ) {
|
}
|
||||||
// get native window handle
|
|
||||||
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
|
|
||||||
|
|
||||||
// set corner preference
|
|
||||||
int cornerPreference = (borderCornerRadius <= 4)
|
|
||||||
? FlatNativeWindowsLibrary.DWMWCP_ROUNDSMALL // 4px
|
|
||||||
: FlatNativeWindowsLibrary.DWMWCP_ROUND; // 8px
|
|
||||||
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, cornerPreference );
|
|
||||||
|
|
||||||
// set border color
|
|
||||||
FlatNativeWindowsLibrary.dwmSetWindowAttributeCOLORREF( hwnd, FlatNativeWindowsLibrary.DWMWA_BORDER_COLOR, borderColor );
|
|
||||||
} else if( SystemInfo.isMacOS ) {
|
|
||||||
if( borderColor == null || borderColor == FlatNativeWindowsLibrary.COLOR_NONE )
|
|
||||||
borderWidth = 0;
|
|
||||||
|
|
||||||
// set corner radius, border width and color
|
|
||||||
FlatNativeMacLibrary.setWindowRoundedBorder( popupWindow, borderCornerRadius,
|
|
||||||
borderWidth, (borderColor != null) ? borderColor.getRGB() : 0 );
|
|
||||||
}
|
}
|
||||||
|
FlatNativeWindowsLibrary.setWindowBorderColor( hwnd, red, green, blue );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void resetWindows11Border( Window popupWindow ) {
|
private static void resetWindows11Border( Window popupWindow ) {
|
||||||
@@ -377,117 +389,6 @@ public class FlatPopupFactory
|
|||||||
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, FlatNativeWindowsLibrary.DWMWCP_DONOTROUND );
|
FlatNativeWindowsLibrary.setWindowCornerPreference( hwnd, FlatNativeWindowsLibrary.DWMWCP_DONOTROUND );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getBorderCornerRadius( Component owner, Component contents ) {
|
|
||||||
String uiKey =
|
|
||||||
(contents instanceof BasicComboPopup) ? "ComboBox.borderCornerRadius" :
|
|
||||||
(contents instanceof JPopupMenu) ? "PopupMenu.borderCornerRadius" :
|
|
||||||
(contents instanceof JToolTip) ? "ToolTip.borderCornerRadius" :
|
|
||||||
"Popup.borderCornerRadius";
|
|
||||||
|
|
||||||
Object value = getOption( owner, contents, FlatClientProperties.POPUP_BORDER_CORNER_RADIUS, uiKey );
|
|
||||||
return (value instanceof Integer) ? (Integer) value : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float getRoundedBorderWidth( Component owner, Component contents ) {
|
|
||||||
String uiKey =
|
|
||||||
(contents instanceof BasicComboPopup) ? "ComboBox.roundedBorderWidth" :
|
|
||||||
(contents instanceof JPopupMenu) ? "PopupMenu.roundedBorderWidth" :
|
|
||||||
(contents instanceof JToolTip) ? "ToolTip.roundedBorderWidth" :
|
|
||||||
"Popup.roundedBorderWidth";
|
|
||||||
|
|
||||||
Object value = getOption( owner, contents, FlatClientProperties.POPUP_ROUNDED_BORDER_WIDTH, uiKey );
|
|
||||||
return (value instanceof Number) ? ((Number)value).floatValue() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- fixes --------------------------------------------------------------
|
|
||||||
|
|
||||||
private static boolean overlapsHeavyWeightComponent( Component owner, Component contents, int x, int y ) {
|
|
||||||
if( owner == null )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Window window = SwingUtilities.getWindowAncestor( owner );
|
|
||||||
if( window == null )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Rectangle r = new Rectangle( new Point( x, y ), contents.getPreferredSize() );
|
|
||||||
return overlapsHeavyWeightComponent( window, r );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean overlapsHeavyWeightComponent( Component parent, Rectangle r ) {
|
|
||||||
if( !parent.isVisible() || !r.intersects( parent.getBounds() ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if( !parent.isLightweight() && !(parent instanceof Window) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if( parent instanceof Container ) {
|
|
||||||
Rectangle r2 = new Rectangle( r.x - parent.getX(), r.y - parent.getY(), r.width, r.height );
|
|
||||||
for( Component c : ((Container)parent).getComponents() ) {
|
|
||||||
if( overlapsHeavyWeightComponent( c, r2 ) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On Linux with Wayland, since Java 21, Swing adds a window focus listener to popup owner/invoker window,
|
|
||||||
* which hides the popup as soon as the owner/invoker window looses focus.
|
|
||||||
* This works fine for light-weight popups.
|
|
||||||
* It also works for heavy-weight popups if they do not request focus.
|
|
||||||
* Because FlatLaf always uses heavy-weight popups, all popups that request focus
|
|
||||||
* are broken since Java 21.
|
|
||||||
*
|
|
||||||
* This method removes the problematic window focus listener.
|
|
||||||
*
|
|
||||||
* https://bugs.openjdk.org/browse/JDK-8280993
|
|
||||||
* https://github.com/openjdk/jdk/pull/13830
|
|
||||||
*/
|
|
||||||
private static void fixLinuxWaylandJava21focusIssue( Component owner ) {
|
|
||||||
// only necessary on Linux when running in Java 21+
|
|
||||||
if( owner == null || !SystemInfo.isLinux || SystemInfo.javaVersion < SystemInfo.toVersion( 21, 0, 0, 0 ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// get window
|
|
||||||
Window window = SwingUtilities.getWindowAncestor( owner );
|
|
||||||
if( window == null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// remove window focus listener, which was added from class sun.awt.UNIXToolkit since Java 21
|
|
||||||
for( WindowFocusListener l : window.getWindowFocusListeners() ) {
|
|
||||||
if( "sun.awt.UNIXToolkit$1".equals( l.getClass().getName() ) ) {
|
|
||||||
window.removeWindowFocusListener( l );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the given popup and, if necessary, fixes the location of a heavy weight popup window.
|
|
||||||
* <p>
|
|
||||||
* 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.
|
|
||||||
* E.g. when opening a dialog on the secondary screen and making combobox popup visible.
|
|
||||||
* <p>
|
|
||||||
* This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8224608
|
|
||||||
*/
|
|
||||||
private static void showPopupAndFixLocation( Popup popup, Window popupWindow ) {
|
|
||||||
if( popupWindow != null ) {
|
|
||||||
// remember location of heavy weight popup window
|
|
||||||
int x = popupWindow.getX();
|
|
||||||
int y = popupWindow.getY();
|
|
||||||
|
|
||||||
popup.show();
|
|
||||||
|
|
||||||
// restore popup window location if it has changed
|
|
||||||
// (probably scaled when screens use different scale factors)
|
|
||||||
if( popupWindow.getX() != x || popupWindow.getY() != y )
|
|
||||||
popupWindow.setLocation( x, y );
|
|
||||||
} else
|
|
||||||
popup.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- class NonFlashingPopup ---------------------------------------------
|
//---- class NonFlashingPopup ---------------------------------------------
|
||||||
|
|
||||||
private static class NonFlashingPopup
|
private static class NonFlashingPopup
|
||||||
@@ -541,9 +442,6 @@ public class FlatPopupFactory
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hide() {
|
public void hide() {
|
||||||
if( contents instanceof JComponent )
|
|
||||||
((JComponent)contents).putClientProperty( KEY_POPUP_USES_NATIVE_BORDER, null );
|
|
||||||
|
|
||||||
if( delegate != null ) {
|
if( delegate != null ) {
|
||||||
delegate.hide();
|
delegate.hide();
|
||||||
delegate = null;
|
delegate = null;
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import javax.swing.CellRendererPane;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
@@ -263,7 +262,7 @@ public class FlatRadioButtonUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
// fill background even if not opaque and if:
|
// fill background even if not opaque if
|
||||||
// - contentAreaFilled is true and
|
// - contentAreaFilled is true and
|
||||||
// - if background color is different to default background color
|
// - if background color is different to default background color
|
||||||
// (this paints selection if using the component as cell renderer)
|
// (this paints selection if using the component as cell renderer)
|
||||||
@@ -279,27 +278,20 @@ public class FlatRadioButtonUI
|
|||||||
int focusWidth = getIconFocusWidth( c );
|
int focusWidth = getIconFocusWidth( c );
|
||||||
if( focusWidth > 0 ) {
|
if( focusWidth > 0 ) {
|
||||||
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
||||||
int halign = ((AbstractButton)c).getHorizontalAlignment();
|
|
||||||
if( halign == SwingConstants.LEADING )
|
|
||||||
halign = ltr ? SwingConstants.LEFT : SwingConstants.RIGHT;
|
|
||||||
else if( halign == SwingConstants.TRAILING )
|
|
||||||
halign = ltr ? SwingConstants.RIGHT : SwingConstants.LEFT;
|
|
||||||
|
|
||||||
Insets insets = c.getInsets( tempInsets );
|
Insets insets = c.getInsets( tempInsets );
|
||||||
if( (focusWidth > insets.left || focusWidth > insets.right) &&
|
int leftOrRightInset = ltr ? insets.left : insets.right;
|
||||||
(halign == SwingConstants.LEFT || halign == SwingConstants.RIGHT) )
|
if( focusWidth > leftOrRightInset ) {
|
||||||
{
|
|
||||||
// The left (or right) inset is smaller than the focus width, which may be
|
// The left (or right) inset is smaller than the focus width, which may be
|
||||||
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
|
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
|
||||||
// In this case the width has been increased in getPreferredSize() and
|
// In this case the width has been increased in getPreferredSize() and
|
||||||
// here it is necessary to fix icon and text painting location.
|
// here it is necessary to fix icon and text painting location.
|
||||||
int offset = (halign == SwingConstants.LEFT)
|
int offset = focusWidth - leftOrRightInset;
|
||||||
? Math.max( focusWidth - insets.left, 0 )
|
if( !ltr )
|
||||||
: -Math.max( focusWidth - insets.right, 0 );
|
offset = -offset;
|
||||||
|
|
||||||
// move the graphics origin to the left (or right)
|
// move the graphics origin to the left (or right)
|
||||||
g.translate( offset, 0 );
|
g.translate( offset, 0 );
|
||||||
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
super.paint( g, c );
|
||||||
g.translate( -offset, 0 );
|
g.translate( -offset, 0 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -336,11 +328,6 @@ public class FlatRadioButtonUI
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getBaseline( JComponent c, int width, int height ) {
|
|
||||||
return FlatButtonUI.getBaselineImpl( c, width, height );
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- class FlatRadioButtonListener --------------------------------------
|
//---- class FlatRadioButtonListener --------------------------------------
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import javax.swing.plaf.RootPaneUI;
|
|||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicRootPaneUI;
|
import javax.swing.plaf.basic.BasicRootPaneUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -155,6 +156,10 @@ public class FlatRootPaneUI
|
|||||||
if( background == null || background instanceof UIResource )
|
if( background == null || background instanceof UIResource )
|
||||||
parent.setBackground( UIManager.getColor( "control" ) );
|
parent.setBackground( UIManager.getColor( "control" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enable dark window appearance on macOS when running in JetBrains Runtime
|
||||||
|
if( SystemInfo.isJetBrainsJVM && SystemInfo.isMacOS_10_14_Mojave_orLater )
|
||||||
|
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -494,7 +499,7 @@ public class FlatRootPaneUI
|
|||||||
@Override
|
@Override
|
||||||
public void invalidateLayout( Container parent ) {
|
public void invalidateLayout( Container parent ) {
|
||||||
if( titlePane != null )
|
if( titlePane != null )
|
||||||
titlePane.menuBarInvalidate();
|
titlePane.menuBarChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
@@ -39,10 +40,13 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
import javax.swing.plaf.basic.BasicScrollBarUI;
|
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.Animator;
|
||||||
|
import com.formdev.flatlaf.util.CubicBezierEasing;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -203,6 +207,16 @@ public class FlatScrollBarUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TrackListener createTrackListener() {
|
||||||
|
return new FlatTrackListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ScrollListener createScrollListener() {
|
||||||
|
return new FlatScrollListener();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener() {
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||||
@@ -245,7 +259,7 @@ public class FlatScrollBarUI
|
|||||||
// because scroll bars do not receive mouse exited event.
|
// because scroll bars do not receive mouse exited event.
|
||||||
// The scroll pane, including its scroll bars, is not part
|
// The scroll pane, including its scroll bars, is not part
|
||||||
// of the component hierarchy and does not receive mouse events
|
// of the component hierarchy and does not receive mouse events
|
||||||
// directly. Instead, LWComponentPeer receives mouse events
|
// directly. Instead LWComponentPeer receives mouse events
|
||||||
// and delegates them to peers, but entered/exited events
|
// and delegates them to peers, but entered/exited events
|
||||||
// are sent only for the whole scroll pane.
|
// are sent only for the whole scroll pane.
|
||||||
// Exited event is only sent when mouse leaves scroll pane.
|
// Exited event is only sent when mouse leaves scroll pane.
|
||||||
@@ -431,6 +445,197 @@ public class FlatScrollBarUI
|
|||||||
return allowsAbsolutePositioning;
|
return allowsAbsolutePositioning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scrollByBlock( int direction ) {
|
||||||
|
runAndSetValueAnimated( () -> {
|
||||||
|
super.scrollByBlock( direction );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scrollByUnit( int direction ) {
|
||||||
|
runAndSetValueAnimated( () -> {
|
||||||
|
super.scrollByUnit( direction );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given runnable, which should modify the scroll bar value,
|
||||||
|
* and then animate scroll bar value from old value to new value.
|
||||||
|
*/
|
||||||
|
public void runAndSetValueAnimated( Runnable r ) {
|
||||||
|
if( inRunAndSetValueAnimated || !isSmoothScrollingEnabled() ) {
|
||||||
|
r.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inRunAndSetValueAnimated = true;
|
||||||
|
|
||||||
|
if( animator != null )
|
||||||
|
animator.cancel();
|
||||||
|
|
||||||
|
if( useValueIsAdjusting )
|
||||||
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
|
// remember current scrollbar value so that we can start scroll animation from there
|
||||||
|
int oldValue = scrollbar.getValue();
|
||||||
|
|
||||||
|
// run given runnable, which computes and sets the new scrollbar value
|
||||||
|
FlatScrollPaneUI.runWithoutBlitting( scrollbar.getParent(), () ->{
|
||||||
|
// if invoked while animation is running, calculation of new value
|
||||||
|
// should start at the previous target value
|
||||||
|
if( targetValue != Integer.MIN_VALUE )
|
||||||
|
scrollbar.setValue( targetValue );
|
||||||
|
|
||||||
|
r.run();
|
||||||
|
} );
|
||||||
|
|
||||||
|
// do not use animation if started dragging thumb
|
||||||
|
if( isDragging ) {
|
||||||
|
// do not clear valueIsAdjusting here
|
||||||
|
inRunAndSetValueAnimated = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newValue = scrollbar.getValue();
|
||||||
|
if( newValue != oldValue ) {
|
||||||
|
// start scroll animation if value has changed
|
||||||
|
setValueAnimated( oldValue, newValue );
|
||||||
|
} else {
|
||||||
|
// clear valueIsAdjusting if value has not changed
|
||||||
|
if( useValueIsAdjusting )
|
||||||
|
scrollbar.setValueIsAdjusting( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
inRunAndSetValueAnimated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean inRunAndSetValueAnimated;
|
||||||
|
private Animator animator;
|
||||||
|
private int startValue = Integer.MIN_VALUE;
|
||||||
|
private int targetValue = Integer.MIN_VALUE;
|
||||||
|
private boolean useValueIsAdjusting = true;
|
||||||
|
|
||||||
|
int getTargetValue() {
|
||||||
|
return targetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueAnimated( int initialValue, int value ) {
|
||||||
|
if( useValueIsAdjusting )
|
||||||
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
|
// (always) set scrollbar value to initial value
|
||||||
|
scrollbar.setValue( initialValue );
|
||||||
|
|
||||||
|
// do some check if animation already running
|
||||||
|
if( animator != null && animator.isRunning() && targetValue != Integer.MIN_VALUE ) {
|
||||||
|
// Ignore requests if animation still running and scroll direction is the same
|
||||||
|
// and new value is within currently running animation.
|
||||||
|
// Without this check, repeating-scrolling via keyboard would become
|
||||||
|
// very slow when reaching the top/bottom/left/right of the viewport,
|
||||||
|
// because it would start a new 200ms animation to scroll a few pixels.
|
||||||
|
if( value == targetValue ||
|
||||||
|
(value > startValue && value < targetValue) || // scroll down/right
|
||||||
|
(value < startValue && value > targetValue) ) // scroll up/left
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startValue = initialValue;
|
||||||
|
targetValue = value;
|
||||||
|
|
||||||
|
// create animator
|
||||||
|
if( animator == null ) {
|
||||||
|
int duration = FlatUIUtils.getUIInt( "ScrollPane.smoothScrolling.duration", 200 );
|
||||||
|
int resolution = FlatUIUtils.getUIInt( "ScrollPane.smoothScrolling.resolution", 10 );
|
||||||
|
Object interpolator = UIManager.get( "ScrollPane.smoothScrolling.interpolator" );
|
||||||
|
|
||||||
|
animator = new Animator( duration, fraction -> {
|
||||||
|
if( scrollbar == null || !scrollbar.isShowing() ) {
|
||||||
|
animator.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-enable valueIsAdjusting if disabled while animation is running
|
||||||
|
// (e.g. in mouse released listener)
|
||||||
|
if( useValueIsAdjusting && !scrollbar.getValueIsAdjusting() )
|
||||||
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
|
scrollbar.setValue( startValue + Math.round( (targetValue - startValue) * fraction ) );
|
||||||
|
}, () -> {
|
||||||
|
startValue = targetValue = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
if( useValueIsAdjusting && scrollbar != null )
|
||||||
|
scrollbar.setValueIsAdjusting( false );
|
||||||
|
});
|
||||||
|
|
||||||
|
animator.setResolution( resolution );
|
||||||
|
animator.setInterpolator( (interpolator instanceof Animator.Interpolator)
|
||||||
|
? (Animator.Interpolator) interpolator
|
||||||
|
: new CubicBezierEasing( 0.5f, 0.5f, 0.5f, 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// restart animator
|
||||||
|
animator.cancel();
|
||||||
|
animator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isSmoothScrollingEnabled() {
|
||||||
|
if( !Animator.useAnimation() || !FlatSystemProperties.getBoolean( FlatSystemProperties.SMOOTH_SCROLLING, true ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if scroll bar is child of scroll pane, check only client property of scroll pane
|
||||||
|
Container parent = scrollbar.getParent();
|
||||||
|
JComponent c = (parent instanceof JScrollPane) ? (JScrollPane) parent : scrollbar;
|
||||||
|
Object smoothScrolling = c.getClientProperty( FlatClientProperties.SCROLL_PANE_SMOOTH_SCROLLING );
|
||||||
|
if( smoothScrolling instanceof Boolean )
|
||||||
|
return (Boolean) smoothScrolling;
|
||||||
|
|
||||||
|
// Note: Getting UI value "ScrollPane.smoothScrolling" here to allow
|
||||||
|
// applications to turn smooth scrolling on or off at any time
|
||||||
|
// (e.g. in application options dialog).
|
||||||
|
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class FlatTrackListener --------------------------------------------
|
||||||
|
|
||||||
|
protected class FlatTrackListener
|
||||||
|
extends TrackListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed( MouseEvent e ) {
|
||||||
|
// Do not use valueIsAdjusting here (in runAndSetValueAnimated())
|
||||||
|
// for smooth scrolling because super.mousePressed() enables this itself
|
||||||
|
// and super.mouseRelease() disables it later.
|
||||||
|
// If we would disable valueIsAdjusting here (in runAndSetValueAnimated())
|
||||||
|
// and move the thumb with the mouse, then the thumb location is not updated
|
||||||
|
// if later scrolled with a key (e.g. HOME key).
|
||||||
|
useValueIsAdjusting = false;
|
||||||
|
|
||||||
|
runAndSetValueAnimated( () -> {
|
||||||
|
super.mousePressed( e );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased( MouseEvent e ) {
|
||||||
|
super.mouseReleased( e );
|
||||||
|
useValueIsAdjusting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class FlatScrollListener -------------------------------------------
|
||||||
|
|
||||||
|
protected class FlatScrollListener
|
||||||
|
extends ScrollListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void actionPerformed( ActionEvent e ) {
|
||||||
|
runAndSetValueAnimated( () -> {
|
||||||
|
super.actionPerformed( e );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- class ScrollBarHoverListener ---------------------------------------
|
//---- class ScrollBarHoverListener ---------------------------------------
|
||||||
|
|
||||||
// using static field to disabling hover for other scroll bars
|
// using static field to disabling hover for other scroll bars
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 FormDev Software GmbH
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
|
||||||
|
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Insets;
|
|
||||||
import javax.swing.JList;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.JTree;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.text.JTextComponent;
|
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Border for {@link javax.swing.JScrollPane}.
|
|
||||||
*
|
|
||||||
* @uiDefault ScrollPane.arc int
|
|
||||||
* @uiDefault ScrollPane.List.arc int
|
|
||||||
* @uiDefault ScrollPane.Table.arc int
|
|
||||||
* @uiDefault ScrollPane.TextComponent.arc int
|
|
||||||
* @uiDefault ScrollPane.Tree.arc int
|
|
||||||
|
|
||||||
* @author Karl Tauber
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public class FlatScrollPaneBorder
|
|
||||||
extends FlatBorder
|
|
||||||
{
|
|
||||||
@Styleable protected int arc = UIManager.getInt( "ScrollPane.arc" );
|
|
||||||
|
|
||||||
private boolean isArcStyled;
|
|
||||||
private final int listArc = FlatUIUtils.getUIInt( "ScrollPane.List.arc", -1 );
|
|
||||||
private final int tableArc = FlatUIUtils.getUIInt( "ScrollPane.Table.arc", -1 );
|
|
||||||
private final int textComponentArc = FlatUIUtils.getUIInt( "ScrollPane.TextComponent.arc", -1 );
|
|
||||||
private final int treeArc = FlatUIUtils.getUIInt( "ScrollPane.Tree.arc", -1 );
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object applyStyleProperty( String key, Object value ) {
|
|
||||||
Object oldValue = super.applyStyleProperty( key, value );
|
|
||||||
|
|
||||||
if( "arc".equals( key ) )
|
|
||||||
isArcStyled = true;
|
|
||||||
|
|
||||||
return oldValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
|
||||||
insets = super.getBorderInsets( c, insets );
|
|
||||||
|
|
||||||
// if view is rounded, increase left and right insets to avoid that the viewport
|
|
||||||
// is painted over the rounded border on the corners
|
|
||||||
int padding = getLeftRightPadding( c );
|
|
||||||
if( padding > 0 ) {
|
|
||||||
insets.left += padding;
|
|
||||||
insets.right += padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
return insets;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getArc( Component c ) {
|
|
||||||
if( isCellEditor( c ) )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if( isArcStyled )
|
|
||||||
return arc;
|
|
||||||
|
|
||||||
if( c instanceof JScrollPane ) {
|
|
||||||
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
|
|
||||||
if( listArc >= 0 && view instanceof JList )
|
|
||||||
return listArc;
|
|
||||||
if( tableArc >= 0 && view instanceof JTable )
|
|
||||||
return tableArc;
|
|
||||||
if( textComponentArc >= 0&& view instanceof JTextComponent )
|
|
||||||
return textComponentArc;
|
|
||||||
if( treeArc >= 0 && view instanceof JTree )
|
|
||||||
return treeArc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return arc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the scaled left/right padding used when arc is larger than zero.
|
|
||||||
* <p>
|
|
||||||
* This is the distance from the inside of the left border to the left side of the view component.
|
|
||||||
* On the right side, this is the distance between the right side of the view component and
|
|
||||||
* the vertical scrollbar. Or the inside of the right border if the scrollbar is hidden.
|
|
||||||
*/
|
|
||||||
public int getLeftRightPadding( Component c ) {
|
|
||||||
// Subtract lineWidth from radius because radius is given for the outside
|
|
||||||
// of the painted line, but insets from super already include lineWidth.
|
|
||||||
// Reduce padding by 10% to make padding slightly smaller because it is not recognizable
|
|
||||||
// when the view is minimally painted over the beginning of the border curve.
|
|
||||||
int arc = getArc( c );
|
|
||||||
return (arc > 0)
|
|
||||||
? Math.max( Math.round( UIScale.scale( ((arc / 2f) - getLineWidth( c )) * 0.9f ) ), 0 )
|
|
||||||
: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,11 +19,10 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.KeyboardFocusManager;
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.LayoutManager;
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ContainerEvent;
|
import java.awt.event.ContainerEvent;
|
||||||
import java.awt.event.ContainerListener;
|
import java.awt.event.ContainerListener;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
@@ -34,6 +33,8 @@ import java.beans.PropertyChangeEvent;
|
|||||||
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.Action;
|
||||||
|
import javax.swing.ActionMap;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -44,19 +45,18 @@ import javax.swing.JTree;
|
|||||||
import javax.swing.JViewport;
|
import javax.swing.JViewport;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.ScrollPaneConstants;
|
import javax.swing.ScrollPaneConstants;
|
||||||
import javax.swing.ScrollPaneLayout;
|
|
||||||
import javax.swing.Scrollable;
|
import javax.swing.Scrollable;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicScrollPaneUI;
|
import javax.swing.plaf.basic.BasicScrollPaneUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
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.Animator;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JScrollPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JScrollPane}.
|
||||||
@@ -103,13 +103,7 @@ public class FlatScrollPaneUI
|
|||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||||
int arc = UIManager.getInt( "ScrollPane.arc" );
|
LookAndFeel.installProperty( c, "opaque", focusWidth == 0 );
|
||||||
LookAndFeel.installProperty( c, "opaque", focusWidth == 0 && arc == 0 );
|
|
||||||
|
|
||||||
// install layout manager
|
|
||||||
LayoutManager layout = c.getLayout();
|
|
||||||
if( layout != null && layout.getClass() == ScrollPaneLayout.UIResource.class )
|
|
||||||
c.setLayout( createScrollPaneLayout() );
|
|
||||||
|
|
||||||
installStyle();
|
installStyle();
|
||||||
|
|
||||||
@@ -120,10 +114,6 @@ public class FlatScrollPaneUI
|
|||||||
public void uninstallUI( JComponent c ) {
|
public void uninstallUI( JComponent c ) {
|
||||||
MigLayoutVisualPadding.uninstall( scrollpane );
|
MigLayoutVisualPadding.uninstall( scrollpane );
|
||||||
|
|
||||||
// uninstall layout manager
|
|
||||||
if( c.getLayout() instanceof FlatScrollPaneLayout )
|
|
||||||
c.setLayout( new ScrollPaneLayout.UIResource() );
|
|
||||||
|
|
||||||
super.uninstallUI( c );
|
super.uninstallUI( c );
|
||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
@@ -146,30 +136,38 @@ public class FlatScrollPaneUI
|
|||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
protected FlatScrollPaneLayout createScrollPaneLayout() {
|
|
||||||
return new FlatScrollPaneLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MouseWheelListener createMouseWheelListener() {
|
protected MouseWheelListener createMouseWheelListener() {
|
||||||
MouseWheelListener superListener = super.createMouseWheelListener();
|
MouseWheelListener superListener = super.createMouseWheelListener();
|
||||||
return e -> {
|
return e -> {
|
||||||
if( isSmoothScrollingEnabled() &&
|
if( isSmoothScrollingEnabled() &&
|
||||||
scrollpane.isWheelScrollingEnabled() &&
|
scrollpane.isWheelScrollingEnabled() )
|
||||||
e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL &&
|
|
||||||
e.getPreciseWheelRotation() != 0 &&
|
|
||||||
e.getPreciseWheelRotation() != e.getWheelRotation() )
|
|
||||||
{
|
{
|
||||||
mouseWheelMovedSmooth( e );
|
if( e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL &&
|
||||||
|
isPreciseWheelEvent( e ) )
|
||||||
|
{
|
||||||
|
// precise scrolling
|
||||||
|
mouseWheelMovedPrecise( e );
|
||||||
|
} else {
|
||||||
|
// smooth scrolling
|
||||||
|
JScrollBar scrollBar = findScrollBarToScroll( e );
|
||||||
|
if( scrollBar != null && scrollBar.getUI() instanceof FlatScrollBarUI ) {
|
||||||
|
FlatScrollBarUI ui = (FlatScrollBarUI) scrollBar.getUI();
|
||||||
|
ui.runAndSetValueAnimated( () -> {
|
||||||
|
superListener.mouseWheelMoved( e );
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
superListener.mouseWheelMoved( e );
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
superListener.mouseWheelMoved( e );
|
superListener.mouseWheelMoved( e );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isSmoothScrollingEnabled() {
|
protected boolean isSmoothScrollingEnabled() {
|
||||||
|
if( !Animator.useAnimation() || !FlatSystemProperties.getBoolean( FlatSystemProperties.SMOOTH_SCROLLING, true ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
Object smoothScrolling = scrollpane.getClientProperty( FlatClientProperties.SCROLL_PANE_SMOOTH_SCROLLING );
|
Object smoothScrolling = scrollpane.getClientProperty( FlatClientProperties.SCROLL_PANE_SMOOTH_SCROLLING );
|
||||||
if( smoothScrolling instanceof Boolean )
|
if( smoothScrolling instanceof Boolean )
|
||||||
return (Boolean) smoothScrolling;
|
return (Boolean) smoothScrolling;
|
||||||
@@ -180,19 +178,40 @@ public class FlatScrollPaneUI
|
|||||||
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mouseWheelMovedSmooth( MouseWheelEvent e ) {
|
private long lastPreciseWheelWhen;
|
||||||
|
|
||||||
|
private boolean isPreciseWheelEvent( MouseWheelEvent e ) {
|
||||||
|
double preciseWheelRotation = e.getPreciseWheelRotation();
|
||||||
|
if( preciseWheelRotation != 0 && preciseWheelRotation != e.getWheelRotation() ) {
|
||||||
|
// precise wheel event
|
||||||
|
lastPreciseWheelWhen = e.getWhen();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a non-precise wheel event occurs shortly after a precise wheel event,
|
||||||
|
// then it is probably still a precise wheel but the precise value
|
||||||
|
// is by chance an integer value (e.g. 1.0 or 2.0).
|
||||||
|
// Not handling this special case, would start an animation for smooth scrolling,
|
||||||
|
// which would be interrupted soon when the next precise wheel event occurs.
|
||||||
|
// This would result in jittery scrolling. E.g. on a MacBook using Trackpad or Magic Mouse.
|
||||||
|
if( e.getWhen() - lastPreciseWheelWhen < 1000 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// non-precise wheel event
|
||||||
|
lastPreciseWheelWhen = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mouseWheelMovedPrecise( MouseWheelEvent e ) {
|
||||||
// return if there is no viewport
|
// return if there is no viewport
|
||||||
JViewport viewport = scrollpane.getViewport();
|
JViewport viewport = scrollpane.getViewport();
|
||||||
if( viewport == null )
|
if( viewport == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// find scrollbar to scroll
|
// find scrollbar to scroll
|
||||||
JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
|
JScrollBar scrollbar = findScrollBarToScroll( e );
|
||||||
if( scrollbar == null || !scrollbar.isVisible() || e.isShiftDown() ) {
|
if( scrollbar == null )
|
||||||
scrollbar = scrollpane.getHorizontalScrollBar();
|
return;
|
||||||
if( scrollbar == null || !scrollbar.isVisible() )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume event
|
// consume event
|
||||||
e.consume();
|
e.consume();
|
||||||
@@ -285,6 +304,16 @@ public class FlatScrollPaneUI
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JScrollBar findScrollBarToScroll( MouseWheelEvent e ) {
|
||||||
|
JScrollBar scrollBar = scrollpane.getVerticalScrollBar();
|
||||||
|
if( scrollBar == null || !scrollBar.isVisible() || e.isShiftDown() ) {
|
||||||
|
scrollBar = scrollpane.getHorizontalScrollBar();
|
||||||
|
if( scrollBar == null || !scrollBar.isVisible() )
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return scrollBar;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener() {
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||||
@@ -313,7 +342,8 @@ public class FlatScrollPaneUI
|
|||||||
Object corner = e.getNewValue();
|
Object corner = e.getNewValue();
|
||||||
if( corner instanceof JButton &&
|
if( corner instanceof JButton &&
|
||||||
((JButton)corner).getBorder() instanceof FlatButtonBorder &&
|
((JButton)corner).getBorder() instanceof FlatButtonBorder &&
|
||||||
getView( scrollpane ) instanceof JTable )
|
scrollpane.getViewport() != null &&
|
||||||
|
scrollpane.getViewport().getView() instanceof JTable )
|
||||||
{
|
{
|
||||||
((JButton)corner).setBorder( BorderFactory.createEmptyBorder() );
|
((JButton)corner).setBorder( BorderFactory.createEmptyBorder() );
|
||||||
((JButton)corner).setFocusable( false );
|
((JButton)corner).setFocusable( false );
|
||||||
@@ -330,18 +360,6 @@ public class FlatScrollPaneUI
|
|||||||
scrollpane.revalidate();
|
scrollpane.revalidate();
|
||||||
scrollpane.repaint();
|
scrollpane.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "border":
|
|
||||||
Object newBorder = e.getNewValue();
|
|
||||||
if( newBorder != null && newBorder == UIManager.getBorder( "Table.scrollPaneBorder" ) ) {
|
|
||||||
// JTable.configureEnclosingScrollPaneUI() replaces the scrollpane border
|
|
||||||
// with another one --> re-apply style on new border
|
|
||||||
borderShared = null;
|
|
||||||
installStyle();
|
|
||||||
scrollpane.revalidate();
|
|
||||||
scrollpane.repaint();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -368,10 +386,9 @@ public class FlatScrollPaneUI
|
|||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected Object applyStyleProperty( String key, Object value ) {
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
if( key.equals( "focusWidth" ) || key.equals( "arc" ) ) {
|
if( key.equals( "focusWidth" ) ) {
|
||||||
int focusWidth = (value instanceof Integer) ? (int) value : UIManager.getInt( "Component.focusWidth" );
|
int focusWidth = (value instanceof Integer) ? (int) value : UIManager.getInt( "Component.focusWidth" );
|
||||||
int arc = (value instanceof Integer) ? (int) value : UIManager.getInt( "ScrollPane.arc" );
|
LookAndFeel.installProperty( scrollpane, "opaque", focusWidth == 0 );
|
||||||
LookAndFeel.installProperty( scrollpane, "opaque", focusWidth == 0 && arc == 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( borderShared == null )
|
if( borderShared == null )
|
||||||
@@ -437,46 +454,13 @@ public class FlatScrollPaneUI
|
|||||||
c.getHeight() - insets.top - insets.bottom );
|
c.getHeight() - insets.top - insets.bottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
// if view is rounded, paint rounded background with view background color
|
|
||||||
// to ensure that free areas at left and right have same color as view
|
|
||||||
Component view;
|
|
||||||
float arc = getBorderArc( scrollpane );
|
|
||||||
if( arc > 0 && (view = getView( scrollpane )) != null ) {
|
|
||||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
|
||||||
|
|
||||||
g.setColor( view.getBackground() );
|
|
||||||
|
|
||||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
|
||||||
FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
|
||||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
|
||||||
}
|
|
||||||
|
|
||||||
paint( g, c );
|
paint( g, c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void paint( Graphics g, JComponent c ) {
|
|
||||||
Border viewportBorder = scrollpane.getViewportBorder();
|
|
||||||
if( viewportBorder != null ) {
|
|
||||||
Rectangle r = scrollpane.getViewportBorderBounds();
|
|
||||||
int padding = getBorderLeftRightPadding( scrollpane );
|
|
||||||
JScrollBar vsb = scrollpane.getVerticalScrollBar();
|
|
||||||
if( padding > 0 &&
|
|
||||||
vsb != null && vsb.isVisible() &&
|
|
||||||
scrollpane.getLayout() instanceof FlatScrollPaneLayout &&
|
|
||||||
((FlatScrollPaneLayout)scrollpane.getLayout()).canIncreaseViewportWidth( scrollpane ) )
|
|
||||||
{
|
|
||||||
boolean ltr = scrollpane.getComponentOrientation().isLeftToRight();
|
|
||||||
int extraWidth = Math.min( padding, vsb.getWidth() );
|
|
||||||
viewportBorder.paintBorder( scrollpane, g, r.x - (ltr ? 0 : extraWidth), r.y, r.width + extraWidth, r.height );
|
|
||||||
} else
|
|
||||||
viewportBorder.paintBorder( scrollpane, g, r.x, r.y, r.width, r.height );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 1.3 */
|
/** @since 1.3 */
|
||||||
public static boolean isPermanentFocusOwner( JScrollPane scrollPane ) {
|
public static boolean isPermanentFocusOwner( JScrollPane scrollPane ) {
|
||||||
Component view = getView( scrollPane );
|
JViewport viewport = scrollPane.getViewport();
|
||||||
|
Component view = (viewport != null) ? viewport.getView() : null;
|
||||||
if( view == null )
|
if( view == null )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -496,23 +480,117 @@ public class FlatScrollPaneUI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Component getView( JScrollPane scrollPane ) {
|
@Override
|
||||||
JViewport viewport = scrollPane.getViewport();
|
protected void syncScrollPaneWithViewport() {
|
||||||
return (viewport != null) ? viewport.getView() : null;
|
// if the viewport has been scrolled by using JComponent.scrollRectToVisible()
|
||||||
|
// (e.g. by moving selection), then it is necessary to update the scroll bar values
|
||||||
|
if( isSmoothScrollingEnabled() ) {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getVerticalScrollBar(), 0, false, () -> {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getHorizontalScrollBar(), 1, false, () -> {
|
||||||
|
super.syncScrollPaneWithViewport();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
super.syncScrollPaneWithViewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float getBorderArc( JScrollPane scrollPane ) {
|
/**
|
||||||
Border border = scrollPane.getBorder();
|
* Runs the given runnable, if smooth scrolling is enabled, with disabled
|
||||||
return (border instanceof FlatScrollPaneBorder)
|
* viewport blitting mode and with scroll bar value set to "target" value.
|
||||||
? UIScale.scale( (float) ((FlatScrollPaneBorder)border).getArc( scrollPane ) )
|
* This is necessary when calculating new view position during animation.
|
||||||
: 0;
|
* Otherwise calculation would use wrong view position and (repeating) scrolling
|
||||||
|
* would be much slower than without smooth scrolling.
|
||||||
|
*/
|
||||||
|
private void runWithScrollBarsTargetValues( boolean blittingOnly, Runnable r ) {
|
||||||
|
if( isSmoothScrollingEnabled() ) {
|
||||||
|
runWithoutBlitting( scrollpane, () -> {
|
||||||
|
if( blittingOnly )
|
||||||
|
r.run();
|
||||||
|
else {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getVerticalScrollBar(), 0, true, () -> {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getHorizontalScrollBar(), 1, true, r );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
r.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getBorderLeftRightPadding( JScrollPane scrollPane ) {
|
private void runAndSyncScrollBarValueAnimated( JScrollBar sb, int i, boolean useTargetValue, Runnable r ) {
|
||||||
Border border = scrollPane.getBorder();
|
if( inRunAndSyncValueAnimated[i] || sb == null || !(sb.getUI() instanceof FlatScrollBarUI) ) {
|
||||||
return (border instanceof FlatScrollPaneBorder)
|
r.run();
|
||||||
? ((FlatScrollPaneBorder)border).getLeftRightPadding( scrollPane )
|
return;
|
||||||
: 0;
|
}
|
||||||
|
|
||||||
|
inRunAndSyncValueAnimated[i] = true;
|
||||||
|
|
||||||
|
int oldValue = sb.getValue();
|
||||||
|
int oldVisibleAmount = sb.getVisibleAmount();
|
||||||
|
int oldMinimum = sb.getMinimum();
|
||||||
|
int oldMaximum = sb.getMaximum();
|
||||||
|
|
||||||
|
FlatScrollBarUI ui = (FlatScrollBarUI) sb.getUI();
|
||||||
|
if( useTargetValue && ui.getTargetValue() != Integer.MIN_VALUE )
|
||||||
|
sb.setValue( ui.getTargetValue() );
|
||||||
|
|
||||||
|
r.run();
|
||||||
|
|
||||||
|
int newValue = sb.getValue();
|
||||||
|
|
||||||
|
if( newValue != oldValue &&
|
||||||
|
sb.getVisibleAmount() == oldVisibleAmount &&
|
||||||
|
sb.getMinimum() == oldMinimum &&
|
||||||
|
sb.getMaximum() == oldMaximum &&
|
||||||
|
sb.getUI() instanceof FlatScrollBarUI )
|
||||||
|
{
|
||||||
|
ui.setValueAnimated( oldValue, newValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
inRunAndSyncValueAnimated[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean[] inRunAndSyncValueAnimated = new boolean[2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given runnable with disabled viewport blitting mode.
|
||||||
|
* If blitting mode is enabled, the viewport immediately repaints parts of the
|
||||||
|
* view if the view position is changed via JViewport.setViewPosition().
|
||||||
|
* This causes scrolling artifacts if smooth scrolling is enabled and the view position
|
||||||
|
* is "temporary" changed to its new target position, changed back to its old position
|
||||||
|
* and again moved animated to the target position.
|
||||||
|
*/
|
||||||
|
static void runWithoutBlitting( Container scrollPane, Runnable r ) {
|
||||||
|
// prevent the viewport to immediately repaint using blitting
|
||||||
|
JViewport viewport = (scrollPane instanceof JScrollPane) ? ((JScrollPane)scrollPane).getViewport() : null;
|
||||||
|
boolean isBlitScrollMode = (viewport != null) ? viewport.getScrollMode() == JViewport.BLIT_SCROLL_MODE : false;
|
||||||
|
if( isBlitScrollMode )
|
||||||
|
viewport.setScrollMode( JViewport.SIMPLE_SCROLL_MODE );
|
||||||
|
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
} finally {
|
||||||
|
if( isBlitScrollMode )
|
||||||
|
viewport.setScrollMode( JViewport.BLIT_SCROLL_MODE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void installSmoothScrollingDelegateActions( JComponent c, boolean blittingOnly, String... actionKeys ) {
|
||||||
|
// get shared action map, used for all components of same type
|
||||||
|
ActionMap map = SwingUtilities.getUIActionMap( c );
|
||||||
|
if( map == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// install actions, but only if not already installed
|
||||||
|
for( String actionKey : actionKeys )
|
||||||
|
installSmoothScrollingDelegateAction( map, blittingOnly, actionKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void installSmoothScrollingDelegateAction( ActionMap map, boolean blittingOnly, String actionKey ) {
|
||||||
|
Action oldAction = map.get( actionKey );
|
||||||
|
if( oldAction == null || oldAction instanceof SmoothScrollingDelegateAction )
|
||||||
|
return; // not found or already installed
|
||||||
|
|
||||||
|
map.put( actionKey, new SmoothScrollingDelegateAction( oldAction, blittingOnly ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class Handler ------------------------------------------------------
|
//---- class Handler ------------------------------------------------------
|
||||||
@@ -537,71 +615,43 @@ public class FlatScrollPaneUI
|
|||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
if( scrollpane.getBorder() instanceof FlatBorder )
|
scrollpane.repaint();
|
||||||
scrollpane.repaint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
// necessary to update focus border
|
// necessary to update focus border
|
||||||
if( scrollpane.getBorder() instanceof FlatBorder )
|
scrollpane.repaint();
|
||||||
scrollpane.repaint();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatScrollPaneLayout -----------------------------------------
|
//---- class SmoothScrollingDelegateAction --------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.3
|
* Used to run component actions with disabled blitting mode and
|
||||||
|
* with scroll bar target values.
|
||||||
*/
|
*/
|
||||||
protected static class FlatScrollPaneLayout
|
private static class SmoothScrollingDelegateAction
|
||||||
extends ScrollPaneLayout.UIResource
|
extends FlatUIAction
|
||||||
{
|
{
|
||||||
|
private final boolean blittingOnly;
|
||||||
|
|
||||||
|
private SmoothScrollingDelegateAction( Action delegate, boolean blittingOnly ) {
|
||||||
|
super( delegate );
|
||||||
|
this.blittingOnly = blittingOnly;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void layoutContainer( Container parent ) {
|
public void actionPerformed( ActionEvent e ) {
|
||||||
super.layoutContainer( parent );
|
Object source = e.getSource();
|
||||||
|
JScrollPane scrollPane = (source instanceof Component)
|
||||||
JScrollPane scrollPane = (JScrollPane) parent;
|
? (JScrollPane) SwingUtilities.getAncestorOfClass( JScrollPane.class, (Component) source )
|
||||||
int padding = getBorderLeftRightPadding( scrollPane );
|
: null;
|
||||||
if( padding > 0 && vsb != null && vsb.isVisible() ) {
|
if( scrollPane != null && scrollPane.getUI() instanceof FlatScrollPaneUI ) {
|
||||||
// move vertical scrollbar to trailing edge
|
((FlatScrollPaneUI)scrollPane.getUI()).runWithScrollBarsTargetValues( blittingOnly,
|
||||||
Insets insets = scrollPane.getInsets();
|
() -> delegate.actionPerformed( e ) );
|
||||||
Rectangle r = vsb.getBounds();
|
} else
|
||||||
int y = Math.max( r.y, insets.top + padding );
|
delegate.actionPerformed( e );
|
||||||
int y2 = Math.min( r.y + r.height, scrollPane.getHeight() - insets.bottom - padding );
|
|
||||||
boolean ltr = scrollPane.getComponentOrientation().isLeftToRight();
|
|
||||||
|
|
||||||
vsb.setBounds( r.x + (ltr ? padding : -padding), y, r.width, y2 - y );
|
|
||||||
|
|
||||||
// increase width of viewport, column header and horizontal scrollbar
|
|
||||||
if( canIncreaseViewportWidth( scrollPane ) ) {
|
|
||||||
int extraWidth = Math.min( padding, vsb.getWidth() );
|
|
||||||
resizeViewport( viewport, extraWidth, ltr );
|
|
||||||
resizeViewport( colHead, extraWidth, ltr );
|
|
||||||
resizeViewport( hsb, extraWidth, ltr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean canIncreaseViewportWidth( JScrollPane scrollPane ) {
|
|
||||||
return scrollPane.getComponentOrientation().isLeftToRight()
|
|
||||||
? !isCornerVisible( upperRight ) && !isCornerVisible( lowerRight )
|
|
||||||
: !isCornerVisible( upperLeft ) && !isCornerVisible( lowerLeft );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isCornerVisible( Component corner ) {
|
|
||||||
return corner != null &&
|
|
||||||
corner.getWidth() > 0 &&
|
|
||||||
corner.getHeight() > 0 &&
|
|
||||||
corner.isVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void resizeViewport( Component c, int extraWidth, boolean ltr ) {
|
|
||||||
if( c == null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Rectangle vr = c.getBounds();
|
|
||||||
c.setBounds( vr.x - (ltr ? 0 : extraWidth), vr.y, vr.width + extraWidth, vr.height );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Canvas;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
@@ -69,8 +67,6 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* <!-- FlatSplitPaneUI -->
|
* <!-- FlatSplitPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||||
* @uiDefault SplitPaneDivider.hoverColor Color optional
|
|
||||||
* @uiDefault SplitPaneDivider.pressedColor Color optional
|
|
||||||
* @uiDefault SplitPaneDivider.oneTouchArrowColor Color
|
* @uiDefault SplitPaneDivider.oneTouchArrowColor Color
|
||||||
* @uiDefault SplitPaneDivider.oneTouchHoverArrowColor Color
|
* @uiDefault SplitPaneDivider.oneTouchHoverArrowColor Color
|
||||||
* @uiDefault SplitPaneDivider.oneTouchPressedArrowColor Color
|
* @uiDefault SplitPaneDivider.oneTouchPressedArrowColor Color
|
||||||
@@ -87,7 +83,6 @@ public class FlatSplitPaneUI
|
|||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
@Styleable protected String arrowType;
|
@Styleable protected String arrowType;
|
||||||
/** @since 3.3 */ @Styleable protected Color draggingColor;
|
|
||||||
@Styleable protected Color oneTouchArrowColor;
|
@Styleable protected Color oneTouchArrowColor;
|
||||||
@Styleable protected Color oneTouchHoverArrowColor;
|
@Styleable protected Color oneTouchHoverArrowColor;
|
||||||
@Styleable protected Color oneTouchPressedArrowColor;
|
@Styleable protected Color oneTouchPressedArrowColor;
|
||||||
@@ -109,8 +104,6 @@ public class FlatSplitPaneUI
|
|||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
arrowType = UIManager.getString( "Component.arrowType" );
|
arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
|
|
||||||
draggingColor = UIManager.getColor( "SplitPaneDivider.draggingColor" );
|
|
||||||
|
|
||||||
// get one-touch colors before invoking super.installDefaults() because they are
|
// get one-touch colors before invoking super.installDefaults() because they are
|
||||||
// used in there on LaF switching
|
// used in there on LaF switching
|
||||||
oneTouchArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchArrowColor" );
|
oneTouchArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchArrowColor" );
|
||||||
@@ -124,8 +117,6 @@ public class FlatSplitPaneUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
draggingColor = null;
|
|
||||||
|
|
||||||
oneTouchArrowColor = null;
|
oneTouchArrowColor = null;
|
||||||
oneTouchHoverArrowColor = null;
|
oneTouchHoverArrowColor = null;
|
||||||
oneTouchPressedArrowColor = null;
|
oneTouchPressedArrowColor = null;
|
||||||
@@ -192,49 +183,12 @@ public class FlatSplitPaneUI
|
|||||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Component createDefaultNonContinuousLayoutDivider() {
|
|
||||||
// only used for non-continuous layout if left or right component is heavy weight
|
|
||||||
return new Canvas() {
|
|
||||||
@Override
|
|
||||||
public void paint( Graphics g ) {
|
|
||||||
if( !isContinuousLayout() && getLastDragLocation() != -1 )
|
|
||||||
paintDragDivider( g, 0 );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finishedPaintingChildren( JSplitPane sp, Graphics g ) {
|
|
||||||
if( sp == splitPane && getLastDragLocation() != -1 && !isContinuousLayout() && !draggingHW )
|
|
||||||
paintDragDivider( g, getLastDragLocation() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void paintDragDivider( Graphics g, int dividerLocation ) {
|
|
||||||
// divider bounds
|
|
||||||
boolean horizontal = (getOrientation() == JSplitPane.HORIZONTAL_SPLIT);
|
|
||||||
int x = horizontal ? dividerLocation : 0;
|
|
||||||
int y = !horizontal ? dividerLocation : 0;
|
|
||||||
int width = horizontal ? dividerSize : splitPane.getWidth();
|
|
||||||
int height = !horizontal ? dividerSize : splitPane.getHeight();
|
|
||||||
|
|
||||||
// paint background
|
|
||||||
g.setColor( FlatUIUtils.deriveColor( draggingColor, splitPane.getBackground() ) );
|
|
||||||
g.fillRect( x, y, width, height );
|
|
||||||
|
|
||||||
// paint divider style (e.g. grip)
|
|
||||||
if( divider instanceof FlatSplitPaneDivider )
|
|
||||||
((FlatSplitPaneDivider)divider).paintStyle( g, x, y, width, height );
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- class FlatSplitPaneDivider -----------------------------------------
|
//---- class FlatSplitPaneDivider -----------------------------------------
|
||||||
|
|
||||||
protected class FlatSplitPaneDivider
|
protected class FlatSplitPaneDivider
|
||||||
extends BasicSplitPaneDivider
|
extends BasicSplitPaneDivider
|
||||||
{
|
{
|
||||||
@Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" );
|
@Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" );
|
||||||
/** @since 3.3 */ @Styleable protected Color hoverColor = UIManager.getColor( "SplitPaneDivider.hoverColor" );
|
|
||||||
/** @since 3.3 */ @Styleable protected Color pressedColor = UIManager.getColor( "SplitPaneDivider.pressedColor" );
|
|
||||||
@Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
|
@Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
|
||||||
@Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
|
@Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
|
||||||
@Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
|
@Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
|
||||||
@@ -297,31 +251,15 @@ public class FlatSplitPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g ) {
|
public void paint( Graphics g ) {
|
||||||
// paint hover or pressed background
|
|
||||||
Color hoverOrPressedColor = (isContinuousLayout() && dragger != null)
|
|
||||||
? pressedColor
|
|
||||||
: (isMouseOver() && dragger == null
|
|
||||||
? hoverColor
|
|
||||||
: null);
|
|
||||||
if( hoverOrPressedColor != null ) {
|
|
||||||
g.setColor( FlatUIUtils.deriveColor( hoverOrPressedColor, splitPane.getBackground() ) );
|
|
||||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
|
||||||
}
|
|
||||||
|
|
||||||
super.paint( g );
|
super.paint( g );
|
||||||
|
|
||||||
paintStyle( g, 0, 0, getWidth(), getHeight() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 3.3 */
|
|
||||||
protected void paintStyle( Graphics g, int x, int y, int width, int height ) {
|
|
||||||
if( "plain".equals( style ) )
|
if( "plain".equals( style ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
|
||||||
g.setColor( gripColor );
|
g.setColor( gripColor );
|
||||||
paintGrip( g, x, y, width, height );
|
paintGrip( g, 0, 0, getWidth(), getHeight() );
|
||||||
|
|
||||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
}
|
}
|
||||||
@@ -348,29 +286,6 @@ public class FlatSplitPaneUI
|
|||||||
: location == (splitPane.getWidth() - getWidth() - insets.right);
|
: location == (splitPane.getWidth() - getWidth() - insets.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setMouseOver( boolean mouseOver ) {
|
|
||||||
super.setMouseOver( mouseOver );
|
|
||||||
repaintIfNecessary();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void prepareForDragging() {
|
|
||||||
super.prepareForDragging();
|
|
||||||
repaintIfNecessary();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finishDraggingTo( int location ) {
|
|
||||||
super.finishDraggingTo( location );
|
|
||||||
repaintIfNecessary();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void repaintIfNecessary() {
|
|
||||||
if( hoverColor != null || pressedColor != null )
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- class FlatOneTouchButton ---------------------------------------
|
//---- class FlatOneTouchButton ---------------------------------------
|
||||||
|
|
||||||
protected class FlatOneTouchButton
|
protected class FlatOneTouchButton
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
@@ -29,15 +28,16 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.CellRendererPane;
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.event.MouseInputListener;
|
import javax.swing.event.MouseInputListener;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicTableHeaderUI;
|
import javax.swing.plaf.basic.BasicTableHeaderUI;
|
||||||
import javax.swing.table.JTableHeader;
|
import javax.swing.table.JTableHeader;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
@@ -114,11 +114,6 @@ public class FlatTableHeaderUI
|
|||||||
public void installUI( JComponent c ) {
|
public void installUI( JComponent c ) {
|
||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
// replace cell renderer pane
|
|
||||||
header.remove( rendererPane );
|
|
||||||
rendererPane = new FlatTableHeaderCellRendererPane();
|
|
||||||
header.add( rendererPane );
|
|
||||||
|
|
||||||
installStyle();
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,8 +265,16 @@ public class FlatTableHeaderUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temporary use own default renderer
|
||||||
|
FlatTableCellHeaderRenderer tempRenderer = new FlatTableCellHeaderRenderer( header.getDefaultRenderer() );
|
||||||
|
header.setDefaultRenderer( tempRenderer );
|
||||||
|
|
||||||
// paint header
|
// paint header
|
||||||
super.paint( g, c );
|
super.paint( g, c );
|
||||||
|
|
||||||
|
// restore default renderer
|
||||||
|
tempRenderer.reset();
|
||||||
|
header.setDefaultRenderer( tempRenderer.delegate );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSystemDefaultRenderer( Object headerRenderer ) {
|
private boolean isSystemDefaultRenderer( Object headerRenderer ) {
|
||||||
@@ -329,129 +332,119 @@ public class FlatTableHeaderUI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatTableHeaderCellRendererPane ------------------------------
|
//---- class FlatTableCellHeaderRenderer ----------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell renderer pane that is used to paint hover and pressed background/foreground
|
* A delegating header renderer that is only used to paint hover and pressed
|
||||||
* and to paint sort arrows at top, bottom or left position.
|
* background/foreground and to paint sort arrows at top, bottom or left position.
|
||||||
*/
|
*/
|
||||||
private class FlatTableHeaderCellRendererPane
|
private class FlatTableCellHeaderRenderer
|
||||||
extends CellRendererPane
|
implements TableCellRenderer, Border, UIResource
|
||||||
{
|
{
|
||||||
private final Icon ascendingSortIcon;
|
private final TableCellRenderer delegate;
|
||||||
private final Icon descendingSortIcon;
|
|
||||||
|
|
||||||
public FlatTableHeaderCellRendererPane() {
|
private JLabel l;
|
||||||
ascendingSortIcon = UIManager.getIcon( "Table.ascendingSortIcon" );
|
private Color oldBackground;
|
||||||
descendingSortIcon = UIManager.getIcon( "Table.descendingSortIcon" );
|
private Color oldForeground;
|
||||||
|
private Boolean oldOpaque;
|
||||||
|
private int oldHorizontalTextPosition = -1;
|
||||||
|
private Border origBorder;
|
||||||
|
private Icon sortIcon;
|
||||||
|
|
||||||
|
FlatTableCellHeaderRenderer( TableCellRenderer delegate ) {
|
||||||
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent( Graphics g, Component c, Container p, int x, int y, int w, int h, boolean shouldValidate ) {
|
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
|
||||||
if( !(c instanceof JLabel) ) {
|
boolean hasFocus, int row, int column )
|
||||||
super.paintComponent( g, c, p, x, y, w, h, shouldValidate );
|
{
|
||||||
return;
|
Component c = delegate.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
|
||||||
}
|
if( !(c instanceof JLabel) )
|
||||||
|
return c;
|
||||||
|
|
||||||
JLabel l = (JLabel) c;
|
l = (JLabel) c;
|
||||||
Color oldBackground = null;
|
|
||||||
Color oldForeground = null;
|
|
||||||
boolean oldOpaque = false;
|
|
||||||
Icon oldIcon = null;
|
|
||||||
int oldHorizontalTextPosition = -1;
|
|
||||||
|
|
||||||
// hover and pressed background/foreground
|
// hover and pressed background/foreground
|
||||||
TableColumn draggedColumn = header.getDraggedColumn();
|
TableColumn draggedColumn = header.getDraggedColumn();
|
||||||
Color background = null;
|
Color background = null;
|
||||||
Color foreground = null;
|
Color foreground = null;
|
||||||
if( draggedColumn != null &&
|
if( draggedColumn != null && header.getTable().convertColumnIndexToView( draggedColumn.getModelIndex() ) == column ) {
|
||||||
header.getTable().convertColumnIndexToView( draggedColumn.getModelIndex() )
|
|
||||||
== getColumn( x - header.getDraggedDistance(), w ) )
|
|
||||||
{
|
|
||||||
background = pressedBackground;
|
background = pressedBackground;
|
||||||
foreground = pressedForeground;
|
foreground = pressedForeground;
|
||||||
} else if( getRolloverColumn() >= 0 && getRolloverColumn() == getColumn( x, w ) ) {
|
} else if( getRolloverColumn() == column ) {
|
||||||
background = hoverBackground;
|
background = hoverBackground;
|
||||||
foreground = hoverForeground;
|
foreground = hoverForeground;
|
||||||
}
|
}
|
||||||
if( background != null ) {
|
if( background != null ) {
|
||||||
oldBackground = l.getBackground();
|
if( oldBackground == null )
|
||||||
oldOpaque = l.isOpaque();
|
oldBackground = l.getBackground();
|
||||||
|
if( oldOpaque == null )
|
||||||
|
oldOpaque = l.isOpaque();
|
||||||
l.setBackground( FlatUIUtils.deriveColor( background, header.getBackground() ) );
|
l.setBackground( FlatUIUtils.deriveColor( background, header.getBackground() ) );
|
||||||
l.setOpaque( true );
|
l.setOpaque( true );
|
||||||
}
|
}
|
||||||
if( foreground != null ) {
|
if( foreground != null ) {
|
||||||
oldForeground = l.getForeground();
|
if( oldForeground == null )
|
||||||
|
oldForeground = l.getForeground();
|
||||||
l.setForeground( FlatUIUtils.deriveColor( foreground, header.getForeground() ) );
|
l.setForeground( FlatUIUtils.deriveColor( foreground, header.getForeground() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort icon position
|
// sort icon
|
||||||
Icon icon = l.getIcon();
|
if( sortIconPosition == SwingConstants.LEFT ) {
|
||||||
boolean isSortIcon = (icon != null && (icon == ascendingSortIcon || icon == descendingSortIcon));
|
// left
|
||||||
if( isSortIcon ) {
|
if( oldHorizontalTextPosition < 0 )
|
||||||
if( sortIconPosition == SwingConstants.LEFT ) {
|
|
||||||
// left
|
|
||||||
oldHorizontalTextPosition = l.getHorizontalTextPosition();
|
oldHorizontalTextPosition = l.getHorizontalTextPosition();
|
||||||
l.setHorizontalTextPosition( SwingConstants.RIGHT );
|
l.setHorizontalTextPosition( SwingConstants.RIGHT );
|
||||||
} else if( sortIconPosition == SwingConstants.TOP || sortIconPosition == SwingConstants.BOTTOM ) {
|
} else if( sortIconPosition == SwingConstants.TOP || sortIconPosition == SwingConstants.BOTTOM ) {
|
||||||
// top or bottom
|
// top or bottom
|
||||||
oldIcon = icon;
|
sortIcon = l.getIcon();
|
||||||
l.setIcon( null );
|
origBorder = l.getBorder();
|
||||||
}
|
l.setIcon( null );
|
||||||
|
l.setBorder( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint renderer component
|
return l;
|
||||||
super.paintComponent( g, c, p, x, y, w, h, shouldValidate );
|
}
|
||||||
|
|
||||||
// paint top or bottom sort icon
|
void reset() {
|
||||||
if( isSortIcon && (sortIconPosition == SwingConstants.TOP || sortIconPosition == SwingConstants.BOTTOM) ) {
|
if( l == null )
|
||||||
int xi = x + ((w - icon.getIconWidth()) / 2);
|
return;
|
||||||
int yi = (sortIconPosition == SwingConstants.TOP)
|
|
||||||
? y + UIScale.scale( 1 )
|
|
||||||
: y + height - icon.getIconHeight()
|
|
||||||
- 1 // for gap
|
|
||||||
- (int) (1 * UIScale.getUserScaleFactor()); // for bottom border
|
|
||||||
icon.paintIcon( c, g, xi, yi );
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore modified renderer component properties
|
if( oldBackground != null )
|
||||||
if( background != null ) {
|
|
||||||
l.setBackground( oldBackground );
|
l.setBackground( oldBackground );
|
||||||
l.setOpaque( oldOpaque );
|
if( oldForeground != null )
|
||||||
}
|
|
||||||
if( foreground != null )
|
|
||||||
l.setForeground( oldForeground );
|
l.setForeground( oldForeground );
|
||||||
if( oldIcon != null )
|
if( oldOpaque != null )
|
||||||
l.setIcon( oldIcon );
|
l.setOpaque( oldOpaque );
|
||||||
if( oldHorizontalTextPosition >= 0 )
|
if( oldHorizontalTextPosition >= 0 )
|
||||||
l.setHorizontalTextPosition( oldHorizontalTextPosition );
|
l.setHorizontalTextPosition( oldHorizontalTextPosition );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get column index for given coordinates.
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
*/
|
if( origBorder != null )
|
||||||
private int getColumn( int x, int width ) {
|
origBorder.paintBorder( c, g, x, y, width, height );
|
||||||
TableColumnModel columnModel = header.getColumnModel();
|
|
||||||
int columnCount = columnModel.getColumnCount();
|
|
||||||
boolean ltr = header.getComponentOrientation().isLeftToRight();
|
|
||||||
int cx = ltr ? 0 : getWidthInRightToLef();
|
|
||||||
|
|
||||||
for( int i = 0; i < columnCount; i++ ) {
|
if( sortIcon != null ) {
|
||||||
int cw = columnModel.getColumn( i ).getWidth();
|
int xi = x + ((width - sortIcon.getIconWidth()) / 2);
|
||||||
if( x == cx - (ltr ? 0 : cw) && width == cw )
|
int yi = (sortIconPosition == SwingConstants.TOP)
|
||||||
return i;
|
? y + UIScale.scale( 1 )
|
||||||
|
: y + height - sortIcon.getIconHeight()
|
||||||
cx += ltr ? cw : -cw;
|
- 1 // for gap
|
||||||
|
- (int) (1 * UIScale.getUserScaleFactor()); // for bottom border
|
||||||
|
sortIcon.paintIcon( c, g, xi, yi );
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// similar to JTableHeader.getWidthInRightToLeft()
|
@Override
|
||||||
private int getWidthInRightToLef() {
|
public Insets getBorderInsets( Component c ) {
|
||||||
JTable table = header.getTable();
|
return (origBorder != null) ? origBorder.getBorderInsets( c ) : new Insets( 0, 0, 0, 0 );
|
||||||
return (table != null && table.getAutoResizeMode() != JTable.AUTO_RESIZE_OFF)
|
}
|
||||||
? table.getWidth()
|
|
||||||
: header.getWidth();
|
@Override
|
||||||
|
public boolean isBorderOpaque() {
|
||||||
|
return (origBorder != null) ? origBorder.isBorderOpaque() : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
@@ -27,25 +26,18 @@ import java.awt.Insets;
|
|||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
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.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.JViewport;
|
import javax.swing.JViewport;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
|
||||||
import javax.swing.plaf.basic.BasicTableUI;
|
import javax.swing.plaf.basic.BasicTableUI;
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
|
||||||
import javax.swing.table.JTableHeader;
|
import javax.swing.table.JTableHeader;
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
|
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
@@ -124,7 +116,6 @@ public class FlatTableUI
|
|||||||
private boolean oldShowHorizontalLines;
|
private boolean oldShowHorizontalLines;
|
||||||
private boolean oldShowVerticalLines;
|
private boolean oldShowVerticalLines;
|
||||||
private Dimension oldIntercellSpacing;
|
private Dimension oldIntercellSpacing;
|
||||||
private TableCellRenderer oldBooleanRenderer;
|
|
||||||
|
|
||||||
private PropertyChangeListener propertyChangeListener;
|
private PropertyChangeListener propertyChangeListener;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
@@ -160,35 +151,19 @@ public class FlatTableUI
|
|||||||
if( rowHeight > 0 )
|
if( rowHeight > 0 )
|
||||||
LookAndFeel.installProperty( table, "rowHeight", UIScale.scale( rowHeight ) );
|
LookAndFeel.installProperty( table, "rowHeight", UIScale.scale( rowHeight ) );
|
||||||
|
|
||||||
FlatTablePropertyWatcher watcher = FlatTablePropertyWatcher.get( table );
|
if( !showHorizontalLines ) {
|
||||||
if( watcher != null )
|
|
||||||
watcher.enabled = false;
|
|
||||||
|
|
||||||
if( !showHorizontalLines && (watcher == null || !watcher.showHorizontalLinesChanged) ) {
|
|
||||||
oldShowHorizontalLines = table.getShowHorizontalLines();
|
oldShowHorizontalLines = table.getShowHorizontalLines();
|
||||||
table.setShowHorizontalLines( false );
|
table.setShowHorizontalLines( false );
|
||||||
}
|
}
|
||||||
if( !showVerticalLines && (watcher == null || !watcher.showVerticalLinesChanged) ) {
|
if( !showVerticalLines ) {
|
||||||
oldShowVerticalLines = table.getShowVerticalLines();
|
oldShowVerticalLines = table.getShowVerticalLines();
|
||||||
table.setShowVerticalLines( false );
|
table.setShowVerticalLines( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( intercellSpacing != null && (watcher == null || !watcher.intercellSpacingChanged) ) {
|
if( intercellSpacing != null ) {
|
||||||
oldIntercellSpacing = table.getIntercellSpacing();
|
oldIntercellSpacing = table.getIntercellSpacing();
|
||||||
table.setIntercellSpacing( intercellSpacing );
|
table.setIntercellSpacing( intercellSpacing );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( watcher != null )
|
|
||||||
watcher.enabled = true;
|
|
||||||
else
|
|
||||||
table.addPropertyChangeListener( new FlatTablePropertyWatcher() );
|
|
||||||
|
|
||||||
// install boolean renderer
|
|
||||||
oldBooleanRenderer = table.getDefaultRenderer( Boolean.class );
|
|
||||||
if( oldBooleanRenderer instanceof UIResource )
|
|
||||||
table.setDefaultRenderer( Boolean.class, new FlatBooleanRenderer() );
|
|
||||||
else
|
|
||||||
oldBooleanRenderer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,36 +177,15 @@ public class FlatTableUI
|
|||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
|
|
||||||
FlatTablePropertyWatcher watcher = FlatTablePropertyWatcher.get( table );
|
|
||||||
if( watcher != null )
|
|
||||||
watcher.enabled = false;
|
|
||||||
|
|
||||||
// restore old show horizontal/vertical lines (if not modified)
|
// restore old show horizontal/vertical lines (if not modified)
|
||||||
if( !showHorizontalLines && oldShowHorizontalLines && !table.getShowHorizontalLines() &&
|
if( !showHorizontalLines && oldShowHorizontalLines && !table.getShowHorizontalLines() )
|
||||||
(watcher == null || !watcher.showHorizontalLinesChanged) )
|
table.setShowHorizontalLines( true );
|
||||||
table.setShowHorizontalLines( true );
|
if( !showVerticalLines && oldShowVerticalLines && !table.getShowVerticalLines() )
|
||||||
if( !showVerticalLines && oldShowVerticalLines && !table.getShowVerticalLines() &&
|
table.setShowVerticalLines( true );
|
||||||
(watcher == null || !watcher.showVerticalLinesChanged) )
|
|
||||||
table.setShowVerticalLines( true );
|
|
||||||
|
|
||||||
// restore old intercell spacing (if not modified)
|
// restore old intercell spacing (if not modified)
|
||||||
if( intercellSpacing != null && table.getIntercellSpacing().equals( intercellSpacing ) &&
|
if( intercellSpacing != null && table.getIntercellSpacing().equals( intercellSpacing ) )
|
||||||
(watcher == null || !watcher.intercellSpacingChanged) )
|
table.setIntercellSpacing( oldIntercellSpacing );
|
||||||
table.setIntercellSpacing( oldIntercellSpacing );
|
|
||||||
|
|
||||||
if( watcher != null )
|
|
||||||
watcher.enabled = true;
|
|
||||||
|
|
||||||
// uninstall boolean renderer
|
|
||||||
if( table.getDefaultRenderer( Boolean.class ) instanceof FlatBooleanRenderer ) {
|
|
||||||
if( oldBooleanRenderer instanceof Component ) {
|
|
||||||
// because the old renderer component was not attached to any component hierarchy,
|
|
||||||
// its UI was not yet updated, and it is necessary to do it here
|
|
||||||
SwingUtilities.updateComponentTreeUI( (Component) oldBooleanRenderer );
|
|
||||||
}
|
|
||||||
table.setDefaultRenderer( Boolean.class, oldBooleanRenderer );
|
|
||||||
}
|
|
||||||
oldBooleanRenderer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -513,70 +467,4 @@ public class FlatTableUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatTablePropertyWatcher -------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener that watches for change of some table properties from application code.
|
|
||||||
* This information is used in {@link FlatTableUI#installDefaults()} and
|
|
||||||
* {@link FlatTableUI#uninstallDefaults()} to decide whether FlatLaf modifies those properties.
|
|
||||||
* If they are modified in application code, FlatLaf no longer changes them.
|
|
||||||
*
|
|
||||||
* The listener is added once for each table, but never removed.
|
|
||||||
* So switching Laf/theme reuses existing listener.
|
|
||||||
*/
|
|
||||||
private static class FlatTablePropertyWatcher
|
|
||||||
implements PropertyChangeListener
|
|
||||||
{
|
|
||||||
boolean enabled = true;
|
|
||||||
boolean showHorizontalLinesChanged;
|
|
||||||
boolean showVerticalLinesChanged;
|
|
||||||
boolean intercellSpacingChanged;
|
|
||||||
|
|
||||||
static FlatTablePropertyWatcher get( JTable table ) {
|
|
||||||
for( PropertyChangeListener l : table.getPropertyChangeListeners() ) {
|
|
||||||
if( l instanceof FlatTablePropertyWatcher )
|
|
||||||
return (FlatTablePropertyWatcher) l;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- interface PropertyChangeListener ----
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void propertyChange( PropertyChangeEvent e ) {
|
|
||||||
if( !enabled )
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch( e.getPropertyName() ) {
|
|
||||||
case "showHorizontalLines": showHorizontalLinesChanged = true; break;
|
|
||||||
case "showVerticalLines": showVerticalLinesChanged = true; break;
|
|
||||||
case "rowMargin": intercellSpacingChanged = true; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---- class FlatBooleanRenderer ------------------------------------------
|
|
||||||
|
|
||||||
private static class FlatBooleanRenderer
|
|
||||||
extends DefaultTableCellRenderer
|
|
||||||
implements UIResource
|
|
||||||
{
|
|
||||||
private boolean selected;
|
|
||||||
|
|
||||||
FlatBooleanRenderer() {
|
|
||||||
setHorizontalAlignment( SwingConstants.CENTER );
|
|
||||||
setIcon( new FlatCheckBoxIcon() {
|
|
||||||
@Override
|
|
||||||
protected boolean isSelected( Component c ) {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue( Object value ) {
|
|
||||||
selected = (value != null && (Boolean) value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,12 @@ public class FlatTextAreaUI
|
|||||||
focusListener = null;
|
focusListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installKeyboardActions() {
|
||||||
|
super.installKeyboardActions();
|
||||||
|
FlatEditorPaneUI.installKeyboardActions( getComponent() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Caret createCaret() {
|
protected Caret createCaret() {
|
||||||
return new FlatCaret( null, false );
|
return new FlatCaret( null, false );
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import javax.swing.JTextField;
|
|||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.SwingConstants;
|
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
@@ -481,21 +480,9 @@ debug*/
|
|||||||
// compute placeholder location
|
// compute placeholder location
|
||||||
Rectangle r = getVisibleEditorRect();
|
Rectangle r = getVisibleEditorRect();
|
||||||
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
FontMetrics fm = c.getFontMetrics( c.getFont() );
|
||||||
int x = r.x;
|
|
||||||
int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2);
|
|
||||||
|
|
||||||
// apply horizontal alignment to x location
|
|
||||||
String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width );
|
String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width );
|
||||||
int stringWidth = fm.stringWidth( clippedPlaceholder );
|
int x = r.x + (isLeftToRight() ? 0 : r.width - fm.stringWidth( clippedPlaceholder ));
|
||||||
int halign = (c instanceof JTextField) ? ((JTextField)c).getHorizontalAlignment() : SwingConstants.LEADING;
|
int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2);
|
||||||
if( halign == SwingConstants.LEADING )
|
|
||||||
halign = isLeftToRight() ? SwingConstants.LEFT : SwingConstants.RIGHT;
|
|
||||||
else if( halign == SwingConstants.TRAILING )
|
|
||||||
halign = isLeftToRight() ? SwingConstants.RIGHT : SwingConstants.LEFT;
|
|
||||||
if( halign == SwingConstants.RIGHT )
|
|
||||||
x += r.width - stringWidth;
|
|
||||||
else if( halign == SwingConstants.CENTER )
|
|
||||||
x = Math.max( 0, x + (r.width / 2) - (stringWidth / 2) );
|
|
||||||
|
|
||||||
// paint placeholder
|
// paint placeholder
|
||||||
g.setColor( placeholderForeground );
|
g.setColor( placeholderForeground );
|
||||||
|
|||||||
@@ -142,6 +142,12 @@ public class FlatTextPaneUI
|
|||||||
focusListener = null;
|
focusListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installKeyboardActions() {
|
||||||
|
super.installKeyboardActions();
|
||||||
|
FlatEditorPaneUI.installKeyboardActions( getComponent() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Caret createCaret() {
|
protected Caret createCaret() {
|
||||||
return new FlatCaret( null, false );
|
return new FlatCaret( null, false );
|
||||||
@@ -156,6 +162,11 @@ public class FlatTextPaneUI
|
|||||||
|
|
||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
FlatEditorPaneUI.propertyChange( getComponent(), e, this::installStyle );
|
FlatEditorPaneUI.propertyChange( getComponent(), e, this::installStyle );
|
||||||
|
|
||||||
|
// BasicEditorPaneUI.propertyChange() re-applied actions from editor kit,
|
||||||
|
// which removed our delegate actions
|
||||||
|
if( "editorKit".equals( propertyName ) )
|
||||||
|
FlatEditorPaneUI.installKeyboardActions( getComponent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
|
|||||||
@@ -608,10 +608,6 @@ public class FlatTitlePane
|
|||||||
doLayout();
|
doLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void menuBarInvalidate() {
|
|
||||||
menuBarPlaceholder.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g ) {
|
public void paint( Graphics g ) {
|
||||||
super.paint( g );
|
super.paint( g );
|
||||||
@@ -839,6 +835,10 @@ public class FlatTitlePane
|
|||||||
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_CLOSING ) );
|
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_CLOSING ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasJBRCustomDecoration() {
|
||||||
|
return window != null && JBRCustomDecorations.hasCustomDecoration( window );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether windows uses native window border and has custom decorations enabled.
|
* Returns whether windows uses native window border and has custom decorations enabled.
|
||||||
*/
|
*/
|
||||||
@@ -896,7 +896,10 @@ public class FlatTitlePane
|
|||||||
iconBounds.width += iconInsets.right;
|
iconBounds.width += iconInsets.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
appIconBounds = iconBounds;
|
if( hasJBRCustomDecoration() )
|
||||||
|
hitTestSpots.add( iconBounds );
|
||||||
|
else
|
||||||
|
appIconBounds = iconBounds;
|
||||||
} else if( showIconBesideTitle && titleLabel.getIcon() != null && titleLabel.getUI() instanceof FlatTitleLabelUI ) {
|
} else if( showIconBesideTitle && titleLabel.getIcon() != null && titleLabel.getUI() instanceof FlatTitleLabelUI ) {
|
||||||
FlatTitleLabelUI ui = (FlatTitleLabelUI) titleLabel.getUI();
|
FlatTitleLabelUI ui = (FlatTitleLabelUI) titleLabel.getUI();
|
||||||
|
|
||||||
@@ -924,7 +927,10 @@ public class FlatTitlePane
|
|||||||
iconR.width += 2;
|
iconR.width += 2;
|
||||||
iconR.height += 2;
|
iconR.height += 2;
|
||||||
|
|
||||||
appIconBounds = iconR;
|
if( hasJBRCustomDecoration() )
|
||||||
|
hitTestSpots.add( iconR );
|
||||||
|
else
|
||||||
|
appIconBounds = iconR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1264,7 +1270,7 @@ debug*/
|
|||||||
public void mouseClicked( MouseEvent e ) {
|
public void mouseClicked( MouseEvent e ) {
|
||||||
// on Linux, when using native library, the mouse clicked event
|
// on Linux, when using native library, the mouse clicked event
|
||||||
// is usually not sent and maximize/restore is done in mouse pressed event
|
// is usually not sent and maximize/restore is done in mouse pressed event
|
||||||
// this check is here for the case that a mouse clicked event comes through for some reason
|
// this check is here for the case that a mouse clicked event comes thru for some reason
|
||||||
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||||
// see comment in mousePressed()
|
// see comment in mousePressed()
|
||||||
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Container;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
@@ -174,12 +173,6 @@ public class FlatToolBarSeparatorUI
|
|||||||
if( size != null )
|
if( size != null )
|
||||||
return scale( size );
|
return scale( size );
|
||||||
|
|
||||||
// get separator width
|
|
||||||
int separatorWidth = this.separatorWidth;
|
|
||||||
FlatToolBarUI toolBarUI = getToolBarUI( c );
|
|
||||||
if( toolBarUI != null && toolBarUI.separatorWidth != null )
|
|
||||||
separatorWidth = toolBarUI.separatorWidth;
|
|
||||||
|
|
||||||
// make sure that gap on left and right side of line have same size
|
// make sure that gap on left and right side of line have same size
|
||||||
int sepWidth = (scale( (separatorWidth - LINE_WIDTH) / 2 ) * 2) + scale( LINE_WIDTH );
|
int sepWidth = (scale( (separatorWidth - LINE_WIDTH) / 2 ) * 2) + scale( LINE_WIDTH );
|
||||||
|
|
||||||
@@ -203,12 +196,6 @@ public class FlatToolBarSeparatorUI
|
|||||||
float lineWidth = scale( 1f );
|
float lineWidth = scale( 1f );
|
||||||
float offset = scale( 2f );
|
float offset = scale( 2f );
|
||||||
|
|
||||||
// get separator color
|
|
||||||
Color separatorColor = this.separatorColor;
|
|
||||||
FlatToolBarUI toolBarUI = getToolBarUI( c );
|
|
||||||
if( toolBarUI != null && toolBarUI.separatorColor != null )
|
|
||||||
separatorColor = toolBarUI.separatorColor;
|
|
||||||
|
|
||||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
g.setColor( separatorColor );
|
g.setColor( separatorColor );
|
||||||
|
|
||||||
@@ -223,11 +210,4 @@ public class FlatToolBarSeparatorUI
|
|||||||
private boolean isVertical( JComponent c ) {
|
private boolean isVertical( JComponent c ) {
|
||||||
return ((JToolBar.Separator)c).getOrientation() == SwingConstants.VERTICAL;
|
return ((JToolBar.Separator)c).getOrientation() == SwingConstants.VERTICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlatToolBarUI getToolBarUI( JComponent c ) {
|
|
||||||
Container parent = c.getParent();
|
|
||||||
return (parent instanceof JToolBar && ((JToolBar)parent).getUI() instanceof FlatToolBarUI)
|
|
||||||
? (FlatToolBarUI) ((JToolBar)parent).getUI()
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,10 +93,6 @@ public class FlatToolBarUI
|
|||||||
@Styleable protected Insets borderMargins;
|
@Styleable protected Insets borderMargins;
|
||||||
@Styleable protected Color gripColor;
|
@Styleable protected Color gripColor;
|
||||||
|
|
||||||
// for FlatToolBarSeparatorUI
|
|
||||||
/** @since 3.3 */ @Styleable protected Integer separatorWidth;
|
|
||||||
/** @since 3.3 */ @Styleable protected Color separatorColor;
|
|
||||||
|
|
||||||
private FocusTraversalPolicy focusTraversalPolicy;
|
private FocusTraversalPolicy focusTraversalPolicy;
|
||||||
private Boolean oldFloatable;
|
private Boolean oldFloatable;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|||||||
@@ -238,6 +238,22 @@ public class FlatTreeUI
|
|||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installKeyboardActions() {
|
||||||
|
super.installKeyboardActions();
|
||||||
|
|
||||||
|
FlatScrollPaneUI.installSmoothScrollingDelegateActions( tree, false,
|
||||||
|
"scrollDownChangeSelection", // PAGE_DOWN
|
||||||
|
"scrollUpChangeSelection", // PAGE_UP
|
||||||
|
"scrollDownChangeLead", // ctrl PAGE_DOWN
|
||||||
|
"scrollUpChangeLead", // ctrl PAGE_UP
|
||||||
|
"scrollDownExtendSelection", // shift PAGE_DOWN, shift ctrl PAGE_DOWN
|
||||||
|
"scrollUpExtendSelection", // shift PAGE_UP, shift ctrl PAGE_UP
|
||||||
|
"selectNextChangeLead", // ctrl DOWN
|
||||||
|
"selectPreviousChangeLead" // ctrl UP
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateRenderer() {
|
protected void updateRenderer() {
|
||||||
super.updateRenderer();
|
super.updateRenderer();
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://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.beans.PropertyChangeListener;
|
||||||
|
import javax.swing.Action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for UI actions used in ActionMap.
|
||||||
|
* (similar to class sun.swing.UIAction)
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
public abstract class FlatUIAction
|
||||||
|
implements Action
|
||||||
|
{
|
||||||
|
protected final String name;
|
||||||
|
protected final Action delegate;
|
||||||
|
|
||||||
|
protected FlatUIAction( String name ) {
|
||||||
|
this.name = name;
|
||||||
|
this.delegate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FlatUIAction( Action delegate ) {
|
||||||
|
this.name = null;
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue( String key ) {
|
||||||
|
if( key == NAME && delegate == null )
|
||||||
|
return name;
|
||||||
|
return (delegate != null) ? delegate.getValue( key ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return (delegate != null) ? delegate.isEnabled() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do nothing in following methods because this class is immutable
|
||||||
|
@Override public void putValue( String key, Object value ) {}
|
||||||
|
@Override public void setEnabled( boolean b ) {}
|
||||||
|
@Override public void addPropertyChangeListener( PropertyChangeListener listener ) {}
|
||||||
|
@Override public void removePropertyChangeListener( PropertyChangeListener listener ) {}
|
||||||
|
}
|
||||||
@@ -299,10 +299,15 @@ public class FlatUIUtils
|
|||||||
if( c == null )
|
if( c == null )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check whether used as table cell editor
|
// check whether used in cell editor (check 3 levels up)
|
||||||
Container parent = c.getParent();
|
Component c2 = c;
|
||||||
if( parent instanceof JTable && ((JTable)parent).getEditorComponent() == c )
|
for( int i = 0; i <= 2 && c2 != null; i++ ) {
|
||||||
return true;
|
Container parent = c2.getParent();
|
||||||
|
if( parent instanceof JTable && ((JTable)parent).getEditorComponent() == c2 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
c2 = parent;
|
||||||
|
}
|
||||||
|
|
||||||
// check whether used as cell editor
|
// check whether used as cell editor
|
||||||
// Table.editor is set in JTable.GenericEditor constructor
|
// Table.editor is set in JTable.GenericEditor constructor
|
||||||
@@ -729,7 +734,7 @@ public class FlatUIUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a (rounded) rectangle used to paint components (border, background, etc.).
|
* Creates a (rounded) rectangle used to paint components (border, background, etc).
|
||||||
* The given arc diameter is limited to min(width,height).
|
* The given arc diameter is limited to min(width,height).
|
||||||
*/
|
*/
|
||||||
public static Shape createComponentRectangle( float x, float y, float w, float h, float arc ) {
|
public static Shape createComponentRectangle( float x, float y, float w, float h, float arc ) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ 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.JViewport;
|
import javax.swing.JViewport;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
@@ -47,9 +48,14 @@ public class FlatViewportUI
|
|||||||
|
|
||||||
Component view = ((JViewport)c).getView();
|
Component view = ((JViewport)c).getView();
|
||||||
if( view instanceof JComponent ) {
|
if( view instanceof JComponent ) {
|
||||||
ComponentUI ui = JavaCompatibility2.getUI( (JComponent) view );
|
try {
|
||||||
if( ui instanceof ViewportPainter )
|
Method m = view.getClass().getMethod( "getUI" );
|
||||||
((ViewportPainter)ui).paintViewport( g, (JComponent) view, (JViewport) c );
|
Object ui = m.invoke( view );
|
||||||
|
if( ui instanceof ViewportPainter )
|
||||||
|
((ViewportPainter)ui).paintViewport( g, (JComponent) view, (JViewport) c );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.HierarchyEvent;
|
||||||
|
import java.awt.event.HierarchyListener;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JRootPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.BorderUIResource;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for custom window decorations provided by JetBrains Runtime (based on OpenJDK).
|
||||||
|
* Requires that the application runs on Windows 10 in a JetBrains Runtime 11 or later.
|
||||||
|
* <ul>
|
||||||
|
* <li><a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime</a></li>
|
||||||
|
* <li><a href="https://github.com/JetBrains/JetBrainsRuntime">https://github.com/JetBrains/JetBrainsRuntime</a></li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class JBRCustomDecorations
|
||||||
|
{
|
||||||
|
private static Boolean supported;
|
||||||
|
private static Method Window_hasCustomDecoration;
|
||||||
|
private static Method Window_setHasCustomDecoration;
|
||||||
|
private static Method WWindowPeer_setCustomDecorationTitleBarHeight;
|
||||||
|
private static Method WWindowPeer_setCustomDecorationHitTestSpots;
|
||||||
|
private static Method AWTAccessor_getComponentAccessor;
|
||||||
|
private static Method AWTAccessor_ComponentAccessor_getPeer;
|
||||||
|
|
||||||
|
public static boolean isSupported() {
|
||||||
|
initialize();
|
||||||
|
return supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object install( JRootPane rootPane ) {
|
||||||
|
if( !isSupported() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// check whether root pane already has a parent, which is the case when switching LaF
|
||||||
|
Container parent = rootPane.getParent();
|
||||||
|
if( parent != null ) {
|
||||||
|
if( parent instanceof Window )
|
||||||
|
FlatNativeWindowBorder.install( (Window) parent );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use hierarchy listener to wait until the root pane is added to a window.
|
||||||
|
// Enabling JBR decorations must be done very early, probably before
|
||||||
|
// window becomes displayable (window.isDisplayable()). Tried also using
|
||||||
|
// "ancestor" property change event on root pane, but this is invoked too late.
|
||||||
|
HierarchyListener addListener = new HierarchyListener() {
|
||||||
|
@Override
|
||||||
|
public void hierarchyChanged( HierarchyEvent e ) {
|
||||||
|
if( e.getChanged() != rootPane || (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Container parent = e.getChangedParent();
|
||||||
|
if( parent instanceof Window )
|
||||||
|
FlatNativeWindowBorder.install( (Window) parent );
|
||||||
|
|
||||||
|
// remove listener since it is actually not possible to uninstall JBR decorations
|
||||||
|
// use invokeLater to remove listener to avoid that listener
|
||||||
|
// is removed while listener queue is processed
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
rootPane.removeHierarchyListener( this );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
rootPane.addHierarchyListener( addListener );
|
||||||
|
return addListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uninstall( JRootPane rootPane, Object data ) {
|
||||||
|
// remove listener (if not yet done)
|
||||||
|
if( data instanceof HierarchyListener )
|
||||||
|
rootPane.removeHierarchyListener( (HierarchyListener) data );
|
||||||
|
|
||||||
|
// since it is actually not possible to uninstall JBR decorations,
|
||||||
|
// simply reduce titleBarHeight so that it is still possible to resize window
|
||||||
|
// and remove hitTestSpots
|
||||||
|
Container parent = rootPane.getParent();
|
||||||
|
if( parent instanceof Window )
|
||||||
|
setHasCustomDecoration( (Window) parent, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean hasCustomDecoration( Window window ) {
|
||||||
|
if( !isSupported() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (Boolean) Window_hasCustomDecoration.invoke( window );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setHasCustomDecoration( Window window, boolean hasCustomDecoration ) {
|
||||||
|
if( !isSupported() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( hasCustomDecoration )
|
||||||
|
Window_setHasCustomDecoration.invoke( window );
|
||||||
|
else
|
||||||
|
setTitleBarHeightAndHitTestSpots( window, 4, Collections.emptyList() );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight, List<Rectangle> hitTestSpots ) {
|
||||||
|
if( !isSupported() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object compAccessor = AWTAccessor_getComponentAccessor.invoke( null );
|
||||||
|
Object peer = AWTAccessor_ComponentAccessor_getPeer.invoke( compAccessor, window );
|
||||||
|
WWindowPeer_setCustomDecorationTitleBarHeight.invoke( peer, titleBarHeight );
|
||||||
|
WWindowPeer_setCustomDecorationHitTestSpots.invoke( peer, hitTestSpots );
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initialize() {
|
||||||
|
if( supported != null )
|
||||||
|
return;
|
||||||
|
supported = false;
|
||||||
|
|
||||||
|
// requires JetBrains Runtime 11 and Windows 10
|
||||||
|
if( !SystemInfo.isJetBrainsJVM_11_orLater || !SystemInfo.isWindows_10_orLater )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> awtAcessorClass = Class.forName( "sun.awt.AWTAccessor" );
|
||||||
|
Class<?> compAccessorClass = Class.forName( "sun.awt.AWTAccessor$ComponentAccessor" );
|
||||||
|
AWTAccessor_getComponentAccessor = awtAcessorClass.getDeclaredMethod( "getComponentAccessor" );
|
||||||
|
AWTAccessor_ComponentAccessor_getPeer = compAccessorClass.getDeclaredMethod( "getPeer", Component.class );
|
||||||
|
|
||||||
|
Class<?> peerClass = Class.forName( "sun.awt.windows.WWindowPeer" );
|
||||||
|
WWindowPeer_setCustomDecorationTitleBarHeight = peerClass.getDeclaredMethod( "setCustomDecorationTitleBarHeight", int.class );
|
||||||
|
WWindowPeer_setCustomDecorationHitTestSpots = peerClass.getDeclaredMethod( "setCustomDecorationHitTestSpots", List.class );
|
||||||
|
WWindowPeer_setCustomDecorationTitleBarHeight.setAccessible( true );
|
||||||
|
WWindowPeer_setCustomDecorationHitTestSpots.setAccessible( true );
|
||||||
|
|
||||||
|
Window_hasCustomDecoration = Window.class.getDeclaredMethod( "hasCustomDecoration" );
|
||||||
|
Window_setHasCustomDecoration = Window.class.getDeclaredMethod( "setHasCustomDecoration" );
|
||||||
|
Window_hasCustomDecoration.setAccessible( true );
|
||||||
|
Window_setHasCustomDecoration.setAccessible( true );
|
||||||
|
|
||||||
|
supported = true;
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class JBRWindowTopBorder -------------------------------------------
|
||||||
|
|
||||||
|
static class JBRWindowTopBorder
|
||||||
|
extends BorderUIResource.EmptyBorderUIResource
|
||||||
|
{
|
||||||
|
private static JBRWindowTopBorder instance;
|
||||||
|
|
||||||
|
private final Color activeLightColor = new Color( 0x707070 );
|
||||||
|
private final Color activeDarkColor = new Color( 0x2D2E2F );
|
||||||
|
private final Color inactiveLightColor = new Color( 0xaaaaaa );
|
||||||
|
private final Color inactiveDarkColor = new Color( 0x494A4B );
|
||||||
|
|
||||||
|
private boolean colorizationAffectsBorders;
|
||||||
|
private Color activeColor;
|
||||||
|
|
||||||
|
static JBRWindowTopBorder getInstance() {
|
||||||
|
if( instance == null )
|
||||||
|
instance = new JBRWindowTopBorder();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
JBRWindowTopBorder() {
|
||||||
|
super( 1, 0, 0, 0 );
|
||||||
|
|
||||||
|
update();
|
||||||
|
installListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
colorizationAffectsBorders = isColorizationColorAffectsBorders();
|
||||||
|
activeColor = calculateActiveBorderColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void installListeners() {
|
||||||
|
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||||
|
toolkit.addPropertyChangeListener( "win.dwm.colorizationColor.affects.borders", e -> {
|
||||||
|
colorizationAffectsBorders = isColorizationColorAffectsBorders();
|
||||||
|
activeColor = calculateActiveBorderColor();
|
||||||
|
} );
|
||||||
|
|
||||||
|
PropertyChangeListener l = e -> {
|
||||||
|
activeColor = calculateActiveBorderColor();
|
||||||
|
};
|
||||||
|
toolkit.addPropertyChangeListener( "win.dwm.colorizationColor", l );
|
||||||
|
toolkit.addPropertyChangeListener( "win.dwm.colorizationColorBalance", l );
|
||||||
|
toolkit.addPropertyChangeListener( "win.frame.activeBorderColor", l );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isColorizationColorAffectsBorders() {
|
||||||
|
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "win.dwm.colorizationColor.affects.borders" );
|
||||||
|
return (value instanceof Boolean) ? (Boolean) value : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getColorizationColor() {
|
||||||
|
return (Color) Toolkit.getDefaultToolkit().getDesktopProperty( "win.dwm.colorizationColor" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int getColorizationColorBalance() {
|
||||||
|
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "win.dwm.colorizationColorBalance" );
|
||||||
|
return (value instanceof Integer) ? (Integer) value : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color calculateActiveBorderColor() {
|
||||||
|
if( !colorizationAffectsBorders )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Color colorizationColor = getColorizationColor();
|
||||||
|
if( colorizationColor != null ) {
|
||||||
|
int colorizationColorBalance = getColorizationColorBalance();
|
||||||
|
if( colorizationColorBalance < 0 || colorizationColorBalance > 100 )
|
||||||
|
colorizationColorBalance = 100;
|
||||||
|
|
||||||
|
if( colorizationColorBalance == 0 )
|
||||||
|
return new Color( 0xD9D9D9 );
|
||||||
|
if( colorizationColorBalance == 100 )
|
||||||
|
return colorizationColor;
|
||||||
|
|
||||||
|
float alpha = colorizationColorBalance / 100.0f;
|
||||||
|
float remainder = 1 - alpha;
|
||||||
|
int r = Math.round( colorizationColor.getRed() * alpha + 0xD9 * remainder );
|
||||||
|
int g = Math.round( colorizationColor.getGreen() * alpha + 0xD9 * remainder );
|
||||||
|
int b = Math.round( colorizationColor.getBlue() * alpha + 0xD9 * remainder );
|
||||||
|
|
||||||
|
// avoid potential IllegalArgumentException in Color constructor
|
||||||
|
r = Math.min( Math.max( r, 0 ), 255 );
|
||||||
|
g = Math.min( Math.max( g, 0 ), 255 );
|
||||||
|
b = Math.min( Math.max( b, 0 ), 255 );
|
||||||
|
|
||||||
|
return new Color( r, g, b );
|
||||||
|
}
|
||||||
|
|
||||||
|
Color activeBorderColor = (Color) Toolkit.getDefaultToolkit().getDesktopProperty( "win.frame.activeBorderColor" );
|
||||||
|
return (activeBorderColor != null) ? activeBorderColor : UIManager.getColor( "MenuBar.borderColor" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
|
boolean active = window != null && window.isActive();
|
||||||
|
boolean dark = FlatLaf.isLafDark();
|
||||||
|
|
||||||
|
g.setColor( active
|
||||||
|
? (activeColor != null ? activeColor : (dark ? activeDarkColor : activeLightColor))
|
||||||
|
: (dark ? inactiveDarkColor : inactiveLightColor) );
|
||||||
|
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
|
g.fillRect( x, y, width, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void repaintBorder( Component c ) {
|
||||||
|
c.repaint( 0, 0, c.getWidth(), 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 FormDev Software GmbH
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.MethodType;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.JList;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.JTree;
|
|
||||||
import javax.swing.plaf.ComponentUI;
|
|
||||||
import javax.swing.text.JTextComponent;
|
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides Java version compatibility methods.
|
|
||||||
* <p>
|
|
||||||
* WARNING: This is private API and may change.
|
|
||||||
*
|
|
||||||
* @author Karl Tauber
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public class JavaCompatibility2
|
|
||||||
{
|
|
||||||
private static boolean getUIMethodInitialized;
|
|
||||||
private static MethodHandle getUIMethod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Java 8: getUI() method on various components (e.g. JButton, JList, etc)
|
|
||||||
* <br>
|
|
||||||
* Java 9: javax.swing.JComponent.getUI()
|
|
||||||
*/
|
|
||||||
public static ComponentUI getUI( JComponent c ) {
|
|
||||||
try {
|
|
||||||
// Java 9+
|
|
||||||
if( SystemInfo.isJava_9_orLater ) {
|
|
||||||
if( !getUIMethodInitialized ) {
|
|
||||||
getUIMethodInitialized = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
MethodType mt = MethodType.methodType( ComponentUI.class, new Class[0] );
|
|
||||||
getUIMethod = MethodHandles.publicLookup().findVirtual( JComponent.class, "getUI", mt );
|
|
||||||
} catch( Exception ex ) {
|
|
||||||
// ignore
|
|
||||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( getUIMethod != null )
|
|
||||||
return (ComponentUI) getUIMethod.invoke( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
// components often used (e.g. as view in scroll panes)
|
|
||||||
if( c instanceof JPanel )
|
|
||||||
return ((JPanel)c).getUI();
|
|
||||||
if( c instanceof JList )
|
|
||||||
return ((JList<?>)c).getUI();
|
|
||||||
if( c instanceof JTable )
|
|
||||||
return ((JTable)c).getUI();
|
|
||||||
if( c instanceof JTree )
|
|
||||||
return ((JTree)c).getUI();
|
|
||||||
if( c instanceof JTextComponent )
|
|
||||||
return ((JTextComponent)c).getUI();
|
|
||||||
|
|
||||||
// Java 8 and fallback
|
|
||||||
Method m = c.getClass().getMethod( "getUI" );
|
|
||||||
return (ComponentUI) m.invoke( c );
|
|
||||||
} catch( Throwable ex ) {
|
|
||||||
// ignore
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -80,7 +80,7 @@ public class FontUtils
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a font family previously registered via {@link #registerFontFamilyLoader(String, Runnable)}.
|
* Loads a font family previously registered via {@link #registerFontFamilyLoader(String, Runnable)}.
|
||||||
* If the family is already loaded or no loader is registered for that family, nothing happens.
|
* If the family is already loaded or no londer is registered for that family, nothing happens.
|
||||||
*/
|
*/
|
||||||
public static void loadFontFamily( String family ) {
|
public static void loadFontFamily( String family ) {
|
||||||
if( !hasLoaders() )
|
if( !hasLoaders() )
|
||||||
@@ -109,7 +109,7 @@ public class FontUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all font family names available in the graphics environment.
|
* Returns all font familiy names available in the graphics environment.
|
||||||
* This invokes {@link GraphicsEnvironment#getAvailableFontFamilyNames()} and
|
* This invokes {@link GraphicsEnvironment#getAvailableFontFamilyNames()} and
|
||||||
* appends families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
|
* appends families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
|
||||||
* to the result.
|
* to the result.
|
||||||
|
|||||||
@@ -192,8 +192,7 @@ public class HiDPIUtils
|
|||||||
|
|
||||||
case "Inter":
|
case "Inter":
|
||||||
case "Inter Light":
|
case "Inter Light":
|
||||||
case "Inter Semi Bold": // Inter v3
|
case "Inter Semi Bold":
|
||||||
case "Inter SemiBold": // Inter v4
|
|
||||||
case "Roboto":
|
case "Roboto":
|
||||||
case "Roboto Light":
|
case "Roboto Light":
|
||||||
case "Roboto Medium":
|
case "Roboto Medium":
|
||||||
|
|||||||
@@ -116,11 +116,7 @@ public class NativeLibrary
|
|||||||
try {
|
try {
|
||||||
// for development environment
|
// for development environment
|
||||||
if( "file".equals( libraryUrl.getProtocol() ) ) {
|
if( "file".equals( libraryUrl.getProtocol() ) ) {
|
||||||
String binPath = libraryUrl.getPath();
|
File libraryFile = new File( libraryUrl.getPath() );
|
||||||
String srcPath = binPath.replace( "flatlaf-core/bin/main/", "flatlaf-core/src/main/resources/" );
|
|
||||||
File libraryFile = new File( srcPath ); // use from 'src' folder if available
|
|
||||||
if( !libraryFile.isFile() )
|
|
||||||
libraryFile = new File( binPath ); // use from 'bin' or 'output' folder if available
|
|
||||||
if( libraryFile.isFile() ) {
|
if( libraryFile.isFile() ) {
|
||||||
// load library without copying
|
// load library without copying
|
||||||
System.load( libraryFile.getCanonicalPath() );
|
System.load( libraryFile.getCanonicalPath() );
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ public class UIScale
|
|||||||
if( SystemInfo.isWindows ) {
|
if( SystemInfo.isWindows ) {
|
||||||
// Special handling for Windows to be compatible with OS scaling,
|
// Special handling for Windows to be compatible with OS scaling,
|
||||||
// which distinguish between "screen scaling" and "text scaling".
|
// which distinguish between "screen scaling" and "text scaling".
|
||||||
// - Windows "screen scaling" scales everything (text, icon, gaps, etc.)
|
// - Windows "screen scaling" scales everything (text, icon, gaps, etc)
|
||||||
// and may have different scaling factors for each screen.
|
// and may have different scaling factors for each screen.
|
||||||
// - Windows "text scaling" increases only the font size, but on all screens.
|
// - Windows "text scaling" increases only the font size, but on all screens.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -20,12 +20,9 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.image.AbstractMultiResolutionImage;
|
import java.awt.image.AbstractMultiResolutionImage;
|
||||||
import java.awt.image.BaseMultiResolutionImage;
|
import java.awt.image.BaseMultiResolutionImage;
|
||||||
import java.awt.image.ImageObserver;
|
|
||||||
import java.awt.image.ImageProducer;
|
|
||||||
import java.awt.image.MultiResolutionImage;
|
import java.awt.image.MultiResolutionImage;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -119,26 +116,6 @@ public class MultiResolutionImageSupport
|
|||||||
return mapAndCacheImage( mrImage );
|
return mapAndCacheImage( mrImage );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWidth( ImageObserver observer ) {
|
|
||||||
return mrImage.getWidth( observer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight( ImageObserver observer ) {
|
|
||||||
return mrImage.getHeight( observer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImageProducer getSource() {
|
|
||||||
return mrImage.getSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getProperty( String name, ImageObserver observer ) {
|
|
||||||
return mrImage.getProperty( name, observer );
|
|
||||||
}
|
|
||||||
|
|
||||||
private Image mapAndCacheImage( Image image ) {
|
private Image mapAndCacheImage( Image image ) {
|
||||||
return cache.computeIfAbsent( image, img -> {
|
return cache.computeIfAbsent( image, img -> {
|
||||||
// using ImageIcon here makes sure that the image is loaded
|
// using ImageIcon here makes sure that the image is loaded
|
||||||
@@ -157,7 +134,7 @@ public class MultiResolutionImageSupport
|
|||||||
{
|
{
|
||||||
private final Dimension[] dimensions;
|
private final Dimension[] dimensions;
|
||||||
private final Function<Dimension, Image> producer;
|
private final Function<Dimension, Image> producer;
|
||||||
private final HashMap<Dimension, Image> cache = new HashMap<>();
|
private final IdentityHashMap<Dimension, Image> cache = new IdentityHashMap<>();
|
||||||
|
|
||||||
ProducerMultiResolutionImage( Dimension[] dimensions, Function<Dimension, Image> producer ) {
|
ProducerMultiResolutionImage( Dimension[] dimensions, Function<Dimension, Image> producer ) {
|
||||||
this.dimensions = dimensions;
|
this.dimensions = dimensions;
|
||||||
@@ -182,16 +159,6 @@ public class MultiResolutionImageSupport
|
|||||||
return produceAndCacheImage( dimensions[0] );
|
return produceAndCacheImage( dimensions[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWidth( ImageObserver observer ) {
|
|
||||||
return dimensions[0].width;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHeight( ImageObserver observer ) {
|
|
||||||
return dimensions[0].height;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Image produceAndCacheImage( Dimension size ) {
|
private Image produceAndCacheImage( Dimension size ) {
|
||||||
return cache.computeIfAbsent( size, size2 -> {
|
return cache.computeIfAbsent( size, size2 -> {
|
||||||
// using ImageIcon here makes sure that the image is loaded
|
// using ImageIcon here makes sure that the image is loaded
|
||||||
|
|||||||
@@ -246,7 +246,6 @@ PasswordField.revealIconColor = @foreground
|
|||||||
|
|
||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
|
|
||||||
[mac]Popup.roundedBorderWidth = 1
|
|
||||||
Popup.dropShadowColor = #000
|
Popup.dropShadowColor = #000
|
||||||
Popup.dropShadowOpacity = 0.25
|
Popup.dropShadowOpacity = 0.25
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,6 @@ ComboBox.popupInsets = 0,0,0,0
|
|||||||
ComboBox.selectionInsets = 0,0,0,0
|
ComboBox.selectionInsets = 0,0,0,0
|
||||||
ComboBox.selectionArc = 0
|
ComboBox.selectionArc = 0
|
||||||
ComboBox.borderCornerRadius = $Popup.borderCornerRadius
|
ComboBox.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
[mac]ComboBox.roundedBorderWidth = $Popup.roundedBorderWidth
|
|
||||||
|
|
||||||
|
|
||||||
#---- Component ----
|
#---- Component ----
|
||||||
@@ -506,7 +505,6 @@ PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
|||||||
#---- Popup ----
|
#---- Popup ----
|
||||||
|
|
||||||
Popup.borderCornerRadius = 4
|
Popup.borderCornerRadius = 4
|
||||||
[mac]Popup.roundedBorderWidth = 0
|
|
||||||
Popup.dropShadowPainted = true
|
Popup.dropShadowPainted = true
|
||||||
Popup.dropShadowInsets = -4,-4,4,4
|
Popup.dropShadowInsets = -4,-4,4,4
|
||||||
|
|
||||||
@@ -516,7 +514,6 @@ Popup.dropShadowInsets = -4,-4,4,4
|
|||||||
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
||||||
PopupMenu.borderInsets = 4,1,4,1
|
PopupMenu.borderInsets = 4,1,4,1
|
||||||
PopupMenu.borderCornerRadius = $Popup.borderCornerRadius
|
PopupMenu.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
[mac]PopupMenu.roundedBorderWidth = $Popup.roundedBorderWidth
|
|
||||||
PopupMenu.background = @menuBackground
|
PopupMenu.background = @menuBackground
|
||||||
PopupMenu.scrollArrowColor = @buttonArrowColor
|
PopupMenu.scrollArrowColor = @buttonArrowColor
|
||||||
|
|
||||||
@@ -600,15 +597,10 @@ ScrollBar.allowsAbsolutePositioning = true
|
|||||||
|
|
||||||
#---- ScrollPane ----
|
#---- ScrollPane ----
|
||||||
|
|
||||||
ScrollPane.border = com.formdev.flatlaf.ui.FlatScrollPaneBorder
|
ScrollPane.border = com.formdev.flatlaf.ui.FlatBorder
|
||||||
ScrollPane.background = $ScrollBar.track
|
ScrollPane.background = $ScrollBar.track
|
||||||
ScrollPane.fillUpperCorner = true
|
ScrollPane.fillUpperCorner = true
|
||||||
ScrollPane.smoothScrolling = true
|
ScrollPane.smoothScrolling = true
|
||||||
ScrollPane.arc = 0
|
|
||||||
#ScrollPane.List.arc = -1
|
|
||||||
#ScrollPane.Table.arc = -1
|
|
||||||
#ScrollPane.TextComponent.arc = -1
|
|
||||||
#ScrollPane.Tree.arc = -1
|
|
||||||
|
|
||||||
|
|
||||||
#---- SearchField ----
|
#---- SearchField ----
|
||||||
@@ -705,8 +697,6 @@ TabbedPane.tabAreaAlignment = leading
|
|||||||
TabbedPane.tabAlignment = center
|
TabbedPane.tabAlignment = center
|
||||||
# allowed values: preferred, equal or compact
|
# allowed values: preferred, equal or compact
|
||||||
TabbedPane.tabWidthMode = preferred
|
TabbedPane.tabWidthMode = preferred
|
||||||
# allowed values: none, auto, left or right
|
|
||||||
TabbedPane.tabRotation = none
|
|
||||||
|
|
||||||
# allowed values: underlined or card
|
# allowed values: underlined or card
|
||||||
TabbedPane.tabType = underlined
|
TabbedPane.tabType = underlined
|
||||||
@@ -741,7 +731,7 @@ Table.showVerticalLines = false
|
|||||||
Table.showTrailingVerticalLine = false
|
Table.showTrailingVerticalLine = false
|
||||||
Table.consistentHomeEndKeyBehavior = true
|
Table.consistentHomeEndKeyBehavior = true
|
||||||
Table.intercellSpacing = 0,0
|
Table.intercellSpacing = 0,0
|
||||||
Table.scrollPaneBorder = com.formdev.flatlaf.ui.FlatScrollPaneBorder
|
Table.scrollPaneBorder = com.formdev.flatlaf.ui.FlatBorder
|
||||||
Table.ascendingSortIcon = com.formdev.flatlaf.icons.FlatAscendingSortIcon
|
Table.ascendingSortIcon = com.formdev.flatlaf.icons.FlatAscendingSortIcon
|
||||||
Table.descendingSortIcon = com.formdev.flatlaf.icons.FlatDescendingSortIcon
|
Table.descendingSortIcon = com.formdev.flatlaf.icons.FlatDescendingSortIcon
|
||||||
Table.sortIconColor = @icon
|
Table.sortIconColor = @icon
|
||||||
@@ -912,7 +902,6 @@ ToolTipManager.enableToolTipMode = activeApplication
|
|||||||
#---- ToolTip ----
|
#---- ToolTip ----
|
||||||
|
|
||||||
ToolTip.borderCornerRadius = $Popup.borderCornerRadius
|
ToolTip.borderCornerRadius = $Popup.borderCornerRadius
|
||||||
[mac]ToolTip.roundedBorderWidth = $Popup.roundedBorderWidth
|
|
||||||
|
|
||||||
|
|
||||||
#---- Tree ----
|
#---- Tree ----
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -295,8 +295,3 @@ ToggleButton.disabledBackground = $Button.disabledBackground
|
|||||||
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
||||||
|
|
||||||
ToggleButton.toolbar.selectedBackground = #fff3
|
ToggleButton.toolbar.selectedBackground = #fff3
|
||||||
|
|
||||||
|
|
||||||
#---- ToolBar ----
|
|
||||||
|
|
||||||
ToolBar.hoverButtonGroupArc = 14
|
|
||||||
|
|||||||
@@ -291,8 +291,3 @@ TextPane.selectionForeground = @textSelectionForeground
|
|||||||
#---- ToggleButton ----
|
#---- ToggleButton ----
|
||||||
|
|
||||||
ToggleButton.disabledBackground = $Button.disabledBackground
|
ToggleButton.disabledBackground = $Button.disabledBackground
|
||||||
|
|
||||||
|
|
||||||
#---- ToolBar ----
|
|
||||||
|
|
||||||
ToolBar.hoverButtonGroupArc = 14
|
|
||||||
|
|||||||
@@ -601,7 +601,7 @@ public class TestFlatStyleableInfo
|
|||||||
);
|
);
|
||||||
|
|
||||||
// border
|
// border
|
||||||
flatScrollPaneBorder( expected );
|
flatBorder( expected );
|
||||||
|
|
||||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||||
}
|
}
|
||||||
@@ -689,9 +689,6 @@ public class TestFlatStyleableInfo
|
|||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
"arrowType", String.class,
|
"arrowType", String.class,
|
||||||
"draggingColor", Color.class,
|
|
||||||
"hoverColor", Color.class,
|
|
||||||
"pressedColor", Color.class,
|
|
||||||
"oneTouchArrowColor", Color.class,
|
"oneTouchArrowColor", Color.class,
|
||||||
"oneTouchHoverArrowColor", Color.class,
|
"oneTouchHoverArrowColor", Color.class,
|
||||||
"oneTouchPressedArrowColor", Color.class,
|
"oneTouchPressedArrowColor", Color.class,
|
||||||
@@ -755,7 +752,6 @@ public class TestFlatStyleableInfo
|
|||||||
"tabAreaAlignment", String.class,
|
"tabAreaAlignment", String.class,
|
||||||
"tabAlignment", String.class,
|
"tabAlignment", String.class,
|
||||||
"tabWidthMode", String.class,
|
"tabWidthMode", String.class,
|
||||||
"tabRotation", String.class,
|
|
||||||
|
|
||||||
"arrowType", String.class,
|
"arrowType", String.class,
|
||||||
"buttonInsets", Insets.class,
|
"buttonInsets", Insets.class,
|
||||||
@@ -929,10 +925,7 @@ public class TestFlatStyleableInfo
|
|||||||
"hoverButtonGroupBackground", Color.class,
|
"hoverButtonGroupBackground", Color.class,
|
||||||
|
|
||||||
"borderMargins", Insets.class,
|
"borderMargins", Insets.class,
|
||||||
"gripColor", Color.class,
|
"gripColor", Color.class
|
||||||
|
|
||||||
"separatorWidth", Integer.class,
|
|
||||||
"separatorColor", Color.class
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||||
@@ -1012,23 +1005,17 @@ public class TestFlatStyleableInfo
|
|||||||
|
|
||||||
expectedMap( expected,
|
expectedMap( expected,
|
||||||
"arc", int.class,
|
"arc", int.class,
|
||||||
|
|
||||||
"roundRect", Boolean.class
|
"roundRect", Boolean.class
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void flatScrollPaneBorder( Map<String, Class<?>> expected ) {
|
|
||||||
flatBorder( expected );
|
|
||||||
|
|
||||||
expectedMap( expected,
|
|
||||||
"arc", int.class
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void flatTextBorder( Map<String, Class<?>> expected ) {
|
private void flatTextBorder( Map<String, Class<?>> expected ) {
|
||||||
flatBorder( expected );
|
flatBorder( expected );
|
||||||
|
|
||||||
expectedMap( expected,
|
expectedMap( expected,
|
||||||
"arc", int.class,
|
"arc", int.class,
|
||||||
|
|
||||||
"roundRect", Boolean.class
|
"roundRect", Boolean.class
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -625,7 +625,7 @@ public class TestFlatStyleableValue
|
|||||||
FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI();
|
FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI();
|
||||||
|
|
||||||
// border
|
// border
|
||||||
flatScrollPaneBorder( c, ui );
|
flatBorder( c, ui );
|
||||||
|
|
||||||
testBoolean( c, ui, "showButtons", true );
|
testBoolean( c, ui, "showButtons", true );
|
||||||
}
|
}
|
||||||
@@ -699,9 +699,6 @@ public class TestFlatStyleableValue
|
|||||||
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
|
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
|
||||||
|
|
||||||
testString( c, ui, "arrowType", "chevron" );
|
testString( c, ui, "arrowType", "chevron" );
|
||||||
testColor( c, ui, "draggingColor", 0x123456 );
|
|
||||||
testColor( c, ui, "hoverColor", 0x123456 );
|
|
||||||
testColor( c, ui, "pressedColor", 0x123456 );
|
|
||||||
testColor( c, ui, "oneTouchArrowColor", 0x123456 );
|
testColor( c, ui, "oneTouchArrowColor", 0x123456 );
|
||||||
testColor( c, ui, "oneTouchHoverArrowColor", 0x123456 );
|
testColor( c, ui, "oneTouchHoverArrowColor", 0x123456 );
|
||||||
testColor( c, ui, "oneTouchPressedArrowColor", 0x123456 );
|
testColor( c, ui, "oneTouchPressedArrowColor", 0x123456 );
|
||||||
@@ -761,7 +758,6 @@ public class TestFlatStyleableValue
|
|||||||
testString( c, ui, "tabAreaAlignment", "leading" );
|
testString( c, ui, "tabAreaAlignment", "leading" );
|
||||||
testString( c, ui, "tabAlignment", "center" );
|
testString( c, ui, "tabAlignment", "center" );
|
||||||
testString( c, ui, "tabWidthMode", "preferred" );
|
testString( c, ui, "tabWidthMode", "preferred" );
|
||||||
testString( c, ui, "tabRotation", "none" );
|
|
||||||
|
|
||||||
testString( c, ui, "arrowType", "chevron" );
|
testString( c, ui, "arrowType", "chevron" );
|
||||||
testInsets( c, ui, "buttonInsets", 1,2,3,4 );
|
testInsets( c, ui, "buttonInsets", 1,2,3,4 );
|
||||||
@@ -906,9 +902,6 @@ public class TestFlatStyleableValue
|
|||||||
|
|
||||||
testInsets( c, ui, "borderMargins", 1,2,3,4 );
|
testInsets( c, ui, "borderMargins", 1,2,3,4 );
|
||||||
testColor( c, ui, "gripColor", 0x123456 );
|
testColor( c, ui, "gripColor", 0x123456 );
|
||||||
|
|
||||||
testInteger( c, ui, "separatorWidth", 123 );
|
|
||||||
testColor( c, ui, "separatorColor", 0x123456 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -972,19 +965,15 @@ public class TestFlatStyleableValue
|
|||||||
flatBorder( c, ui );
|
flatBorder( c, ui );
|
||||||
|
|
||||||
testInteger( c, ui, "arc", 123 );
|
testInteger( c, ui, "arc", 123 );
|
||||||
|
|
||||||
testBoolean( c, ui, "roundRect", true );
|
testBoolean( c, ui, "roundRect", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void flatScrollPaneBorder( JComponent c, StyleableUI ui ) {
|
|
||||||
flatBorder( c, ui );
|
|
||||||
|
|
||||||
testInteger( c, ui, "arc", 123 );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void flatTextBorder( JComponent c, StyleableUI ui ) {
|
private void flatTextBorder( JComponent c, StyleableUI ui ) {
|
||||||
flatBorder( c, ui );
|
flatBorder( c, ui );
|
||||||
|
|
||||||
testInteger( c, ui, "arc", 123 );
|
testInteger( c, ui, "arc", 123 );
|
||||||
|
|
||||||
testBoolean( c, ui, "roundRect", true );
|
testBoolean( c, ui, "roundRect", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,17 +1034,6 @@ public class TestFlatStyleableValue
|
|||||||
// FlatRoundBorder extends FlatBorder
|
// FlatRoundBorder extends FlatBorder
|
||||||
flatBorder( border );
|
flatBorder( border );
|
||||||
|
|
||||||
testValue( border, "arc", 6 );
|
|
||||||
testValue( border, "roundRect", true );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void flatScrollPaneBorder() {
|
|
||||||
FlatScrollPaneBorder border = new FlatScrollPaneBorder();
|
|
||||||
|
|
||||||
// FlatScrollPaneBorder extends FlatBorder
|
|
||||||
flatBorder( border );
|
|
||||||
|
|
||||||
testValue( border, "arc", 6 );
|
testValue( border, "arc", 6 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1067,7 +1045,6 @@ public class TestFlatStyleableValue
|
|||||||
flatBorder( border );
|
flatBorder( border );
|
||||||
|
|
||||||
testValue( border, "arc", 6 );
|
testValue( border, "arc", 6 );
|
||||||
testValue( border, "roundRect", true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ public class TestFlatStyling
|
|||||||
FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI();
|
FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI();
|
||||||
|
|
||||||
// border
|
// border
|
||||||
flatScrollPaneBorder( style -> ui.applyStyle( style ) );
|
flatBorder( style -> ui.applyStyle( style ) );
|
||||||
|
|
||||||
ui.applyStyle( "showButtons: true" );
|
ui.applyStyle( "showButtons: true" );
|
||||||
|
|
||||||
@@ -870,9 +870,6 @@ public class TestFlatStyling
|
|||||||
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
|
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
|
||||||
|
|
||||||
ui.applyStyle( "arrowType: chevron" );
|
ui.applyStyle( "arrowType: chevron" );
|
||||||
ui.applyStyle( "draggingColor: #fff" );
|
|
||||||
ui.applyStyle( "hoverColor: #fff" );
|
|
||||||
ui.applyStyle( "pressedColor: #fff" );
|
|
||||||
ui.applyStyle( "oneTouchArrowColor: #fff" );
|
ui.applyStyle( "oneTouchArrowColor: #fff" );
|
||||||
ui.applyStyle( "oneTouchHoverArrowColor: #fff" );
|
ui.applyStyle( "oneTouchHoverArrowColor: #fff" );
|
||||||
ui.applyStyle( "oneTouchPressedArrowColor: #fff" );
|
ui.applyStyle( "oneTouchPressedArrowColor: #fff" );
|
||||||
@@ -940,7 +937,6 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "tabAreaAlignment: leading" );
|
ui.applyStyle( "tabAreaAlignment: leading" );
|
||||||
ui.applyStyle( "tabAlignment: center" );
|
ui.applyStyle( "tabAlignment: center" );
|
||||||
ui.applyStyle( "tabWidthMode: preferred" );
|
ui.applyStyle( "tabWidthMode: preferred" );
|
||||||
ui.applyStyle( "tabRotation: none" );
|
|
||||||
|
|
||||||
ui.applyStyle( "arrowType: chevron" );
|
ui.applyStyle( "arrowType: chevron" );
|
||||||
ui.applyStyle( "buttonInsets: 1,2,3,4" );
|
ui.applyStyle( "buttonInsets: 1,2,3,4" );
|
||||||
@@ -1150,9 +1146,6 @@ public class TestFlatStyling
|
|||||||
ui.applyStyle( "borderMargins: 1,2,3,4" );
|
ui.applyStyle( "borderMargins: 1,2,3,4" );
|
||||||
ui.applyStyle( "gripColor: #fff" );
|
ui.applyStyle( "gripColor: #fff" );
|
||||||
|
|
||||||
ui.applyStyle( "separatorWidth: 6" );
|
|
||||||
ui.applyStyle( "separatorColor: #fff" );
|
|
||||||
|
|
||||||
// JComponent properties
|
// JComponent properties
|
||||||
ui.applyStyle( "background: #fff" );
|
ui.applyStyle( "background: #fff" );
|
||||||
ui.applyStyle( "foreground: #fff" );
|
ui.applyStyle( "foreground: #fff" );
|
||||||
@@ -1241,19 +1234,15 @@ public class TestFlatStyling
|
|||||||
flatBorder( applyStyle );
|
flatBorder( applyStyle );
|
||||||
|
|
||||||
applyStyle.accept( "arc: 6" );
|
applyStyle.accept( "arc: 6" );
|
||||||
|
|
||||||
applyStyle.accept( "roundRect: true" );
|
applyStyle.accept( "roundRect: true" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void flatScrollPaneBorder( Consumer<String> applyStyle ) {
|
|
||||||
flatBorder( applyStyle );
|
|
||||||
|
|
||||||
applyStyle.accept( "arc: 6" );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void flatTextBorder( Consumer<String> applyStyle ) {
|
private void flatTextBorder( Consumer<String> applyStyle ) {
|
||||||
flatBorder( applyStyle );
|
flatBorder( applyStyle );
|
||||||
|
|
||||||
applyStyle.accept( "arc: 6" );
|
applyStyle.accept( "arc: 6" );
|
||||||
|
|
||||||
applyStyle.accept( "roundRect: true" );
|
applyStyle.accept( "roundRect: true" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import javax.swing.plaf.metal.MetalLookAndFeel;
|
|||||||
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
|
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
|
||||||
import com.formdev.flatlaf.*;
|
import com.formdev.flatlaf.*;
|
||||||
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
|
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
|
||||||
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
|
||||||
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -68,8 +66,6 @@ class ControlBar
|
|||||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Dark (F2)", FlatDarkLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Dark (F2)", FlatDarkLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf IntelliJ (F3)", FlatIntelliJLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf IntelliJ (F3)", FlatIntelliJLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
||||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf macOS Light (F5)", FlatMacLightLaf.class.getName() ) );
|
|
||||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf macOS Dark (F6)", FlatMacDarkLaf.class.getName() ) );
|
|
||||||
|
|
||||||
UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
|
UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
|
||||||
for( UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels ) {
|
for( UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels ) {
|
||||||
@@ -131,8 +127,6 @@ class ControlBar
|
|||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F2, FlatDarkLaf.class.getName() );
|
registerSwitchToLookAndFeel( KeyEvent.VK_F2, FlatDarkLaf.class.getName() );
|
||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F3, FlatIntelliJLaf.class.getName() );
|
registerSwitchToLookAndFeel( KeyEvent.VK_F3, FlatIntelliJLaf.class.getName() );
|
||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F4, FlatDarculaLaf.class.getName() );
|
registerSwitchToLookAndFeel( KeyEvent.VK_F4, FlatDarculaLaf.class.getName() );
|
||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F5, FlatMacLightLaf.class.getName() );
|
|
||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F6, FlatMacDarkLaf.class.getName() );
|
|
||||||
|
|
||||||
if( SystemInfo.isWindows )
|
if( SystemInfo.isWindows )
|
||||||
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
|
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.demo;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
@@ -115,16 +116,15 @@ class DataComponentsPanel
|
|||||||
table1.setGridColor( redGridColorCheckBox.isSelected() ? Color.red : UIManager.getColor( "Table.gridColor" ) );
|
table1.setGridColor( redGridColorCheckBox.isSelected() ? Color.red : UIManager.getColor( "Table.gridColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showHorizontalLinesPropertyChange() {
|
@Override
|
||||||
showHorizontalLinesCheckBox.setSelected( table1.getShowHorizontalLines() );
|
public void updateUI() {
|
||||||
}
|
super.updateUI();
|
||||||
|
|
||||||
private void showVerticalLinesPropertyChange() {
|
EventQueue.invokeLater( () -> {
|
||||||
showVerticalLinesCheckBox.setSelected( table1.getShowVerticalLines() );
|
showHorizontalLinesChanged();
|
||||||
}
|
showVerticalLinesChanged();
|
||||||
|
intercellSpacingChanged();
|
||||||
private void intercellSpacingPropertyChange() {
|
} );
|
||||||
intercellSpacingCheckBox.setSelected( table1.getRowMargin() != 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||||
@@ -333,10 +333,10 @@ class DataComponentsPanel
|
|||||||
"Not editable", "Text", "Combo", "Combo Editable", "Integer", "Boolean"
|
"Not editable", "Text", "Combo", "Combo Editable", "Integer", "Boolean"
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Class<?>[] columnTypes = {
|
Class<?>[] columnTypes = new Class<?>[] {
|
||||||
Object.class, Object.class, String.class, String.class, Integer.class, Boolean.class
|
Object.class, Object.class, String.class, String.class, Integer.class, Boolean.class
|
||||||
};
|
};
|
||||||
boolean[] columnEditable = {
|
boolean[] columnEditable = new boolean[] {
|
||||||
false, true, true, true, true, true
|
false, true, true, true, true, true
|
||||||
};
|
};
|
||||||
@Override
|
@Override
|
||||||
@@ -383,9 +383,6 @@ class DataComponentsPanel
|
|||||||
}
|
}
|
||||||
table1.setAutoCreateRowSorter(true);
|
table1.setAutoCreateRowSorter(true);
|
||||||
table1.setComponentPopupMenu(popupMenu2);
|
table1.setComponentPopupMenu(popupMenu2);
|
||||||
table1.addPropertyChangeListener("showHorizontalLines", e -> showHorizontalLinesPropertyChange());
|
|
||||||
table1.addPropertyChangeListener("showVerticalLines", e -> showVerticalLinesPropertyChange());
|
|
||||||
table1.addPropertyChangeListener("rowMargin", e -> intercellSpacingPropertyChange());
|
|
||||||
scrollPane5.setViewportView(table1);
|
scrollPane5.setViewportView(table1);
|
||||||
}
|
}
|
||||||
add(scrollPane5, "cell 1 3 3 1,width 300");
|
add(scrollPane5, "cell 1 3 3 1,width 300");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8"
|
JFDML JFormDesigner: "8.0.0.0.194" Java: "17.0.2" encoding: "UTF-8"
|
||||||
|
|
||||||
new FormModel {
|
new FormModel {
|
||||||
contentType: "form/swing"
|
contentType: "form/swing"
|
||||||
@@ -333,9 +333,6 @@ new FormModel {
|
|||||||
auxiliary() {
|
auxiliary() {
|
||||||
"JavaCodeGenerator.variableLocal": false
|
"JavaCodeGenerator.variableLocal": false
|
||||||
}
|
}
|
||||||
addEvent( new FormEvent( "java.beans.PropertyChangeListener", "propertyChange", "showHorizontalLinesPropertyChange", false, "showHorizontalLines" ) )
|
|
||||||
addEvent( new FormEvent( "java.beans.PropertyChangeListener", "propertyChange", "showVerticalLinesPropertyChange", false, "showVerticalLines" ) )
|
|
||||||
addEvent( new FormEvent( "java.beans.PropertyChangeListener", "propertyChange", "intercellSpacingPropertyChange", false, "rowMargin" ) )
|
|
||||||
} )
|
} )
|
||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 1 3 3 1,width 300"
|
"value": "cell 1 3 3 1,width 300"
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.formdev.flatlaf.FlatDarkLaf;
|
|||||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.FlatLightLaf;
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
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.*;
|
||||||
@@ -46,6 +47,7 @@ import com.formdev.flatlaf.icons.FlatAbstractIcon;
|
|||||||
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
||||||
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
||||||
import com.formdev.flatlaf.extras.FlatSVGUtils;
|
import com.formdev.flatlaf.extras.FlatSVGUtils;
|
||||||
|
import com.formdev.flatlaf.ui.JBRCustomDecorations;
|
||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
import com.formdev.flatlaf.util.FontUtils;
|
import com.formdev.flatlaf.util.FontUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
@@ -265,6 +267,18 @@ class DemoFrame
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void animationChanged() {
|
||||||
|
boolean enabled = animationMenuItem.isSelected();
|
||||||
|
System.setProperty( FlatSystemProperties.ANIMATION, Boolean.toString( enabled ) );
|
||||||
|
|
||||||
|
smoothScrollingMenuItem.setEnabled( enabled );
|
||||||
|
animatedLafChangeMenuItem.setEnabled( enabled );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void smoothScrollingChanged() {
|
||||||
|
UIManager.put( "ScrollPane.smoothScrolling", smoothScrollingMenuItem.isSelected() );
|
||||||
|
}
|
||||||
|
|
||||||
private void animatedLafChangeChanged() {
|
private void animatedLafChangeChanged() {
|
||||||
System.setProperty( "flatlaf.animatedLafChange", String.valueOf( animatedLafChangeMenuItem.isSelected() ) );
|
System.setProperty( "flatlaf.animatedLafChange", String.valueOf( animatedLafChangeMenuItem.isSelected() ) );
|
||||||
}
|
}
|
||||||
@@ -504,6 +518,8 @@ class DemoFrame
|
|||||||
showTitleBarIconMenuItem = new JCheckBoxMenuItem();
|
showTitleBarIconMenuItem = new JCheckBoxMenuItem();
|
||||||
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
|
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
|
||||||
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
|
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
|
||||||
|
animationMenuItem = new JCheckBoxMenuItem();
|
||||||
|
smoothScrollingMenuItem = new JCheckBoxMenuItem();
|
||||||
animatedLafChangeMenuItem = new JCheckBoxMenuItem();
|
animatedLafChangeMenuItem = new JCheckBoxMenuItem();
|
||||||
JMenuItem showHintsMenuItem = new JMenuItem();
|
JMenuItem showHintsMenuItem = new JMenuItem();
|
||||||
JMenuItem showUIDefaultsInspectorMenuItem = new JMenuItem();
|
JMenuItem showUIDefaultsInspectorMenuItem = new JMenuItem();
|
||||||
@@ -791,6 +807,19 @@ class DemoFrame
|
|||||||
alwaysShowMnemonicsMenuItem.setText("Always show mnemonics");
|
alwaysShowMnemonicsMenuItem.setText("Always show mnemonics");
|
||||||
alwaysShowMnemonicsMenuItem.addActionListener(e -> alwaysShowMnemonics());
|
alwaysShowMnemonicsMenuItem.addActionListener(e -> alwaysShowMnemonics());
|
||||||
optionsMenu.add(alwaysShowMnemonicsMenuItem);
|
optionsMenu.add(alwaysShowMnemonicsMenuItem);
|
||||||
|
optionsMenu.addSeparator();
|
||||||
|
|
||||||
|
//---- animationMenuItem ----
|
||||||
|
animationMenuItem.setText("Animation");
|
||||||
|
animationMenuItem.setSelected(true);
|
||||||
|
animationMenuItem.addActionListener(e -> animationChanged());
|
||||||
|
optionsMenu.add(animationMenuItem);
|
||||||
|
|
||||||
|
//---- smoothScrollingMenuItem ----
|
||||||
|
smoothScrollingMenuItem.setText("Smooth Scrolling");
|
||||||
|
smoothScrollingMenuItem.setSelected(true);
|
||||||
|
smoothScrollingMenuItem.addActionListener(e -> smoothScrollingChanged());
|
||||||
|
optionsMenu.add(smoothScrollingMenuItem);
|
||||||
|
|
||||||
//---- animatedLafChangeMenuItem ----
|
//---- animatedLafChangeMenuItem ----
|
||||||
animatedLafChangeMenuItem.setText("Animated Laf Change");
|
animatedLafChangeMenuItem.setText("Animated Laf Change");
|
||||||
@@ -930,6 +959,12 @@ class DemoFrame
|
|||||||
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||||
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||||
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
|
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
|
||||||
|
|
||||||
|
if( JBRCustomDecorations.isSupported() ) {
|
||||||
|
// If the JetBrains Runtime is used, it forces the use of it's own custom
|
||||||
|
// window decoration, which can not disabled.
|
||||||
|
windowDecorationsCheckBoxMenuItem.setEnabled( false );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsupported( windowDecorationsCheckBoxMenuItem );
|
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||||
unsupported( menuBarEmbeddedCheckBoxMenuItem );
|
unsupported( menuBarEmbeddedCheckBoxMenuItem );
|
||||||
@@ -974,6 +1009,8 @@ class DemoFrame
|
|||||||
private JCheckBoxMenuItem showTitleBarIconMenuItem;
|
private JCheckBoxMenuItem showTitleBarIconMenuItem;
|
||||||
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
|
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
|
||||||
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
|
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
|
||||||
|
private JCheckBoxMenuItem animationMenuItem;
|
||||||
|
private JCheckBoxMenuItem smoothScrollingMenuItem;
|
||||||
private JCheckBoxMenuItem animatedLafChangeMenuItem;
|
private JCheckBoxMenuItem animatedLafChangeMenuItem;
|
||||||
private JMenuItem aboutMenuItem;
|
private JMenuItem aboutMenuItem;
|
||||||
private JToolBar toolBar;
|
private JToolBar toolBar;
|
||||||
|
|||||||
@@ -418,6 +418,27 @@ new FormModel {
|
|||||||
}
|
}
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "alwaysShowMnemonics", false ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "alwaysShowMnemonics", false ) )
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||||
|
name: "separator9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||||
|
name: "animationMenuItem"
|
||||||
|
"text": "Animation"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "animationChanged", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||||
|
name: "smoothScrollingMenuItem"
|
||||||
|
"text": "Smooth Scrolling"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smoothScrollingChanged", false ) )
|
||||||
|
} )
|
||||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||||
name: "animatedLafChangeMenuItem"
|
name: "animatedLafChangeMenuItem"
|
||||||
"text": "Animated Laf Change"
|
"text": "Animated Laf Change"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class ScrollablePanel
|
|||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredScrollableViewportSize() {
|
public Dimension getPreferredScrollableViewportSize() {
|
||||||
return new Dimension( getPreferredSize().width, UIScale.scale( 400 ) );
|
return UIScale.scale( new Dimension( 400, 400 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,7 +49,7 @@ public class ScrollablePanel
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getScrollableTracksViewportWidth() {
|
public boolean getScrollableTracksViewportWidth() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ class TabsPanel
|
|||||||
private void closeButtonStyleChanged() {
|
private void closeButtonStyleChanged() {
|
||||||
// WARNING:
|
// WARNING:
|
||||||
// Do not use this trick to style individual tabbed panes in own code.
|
// Do not use this trick to style individual tabbed panes in own code.
|
||||||
// Instead, use one styling for all tabbed panes in your application.
|
// Instead use one styling for all tabbed panes in your application.
|
||||||
if( circleCloseButton.isSelected() ) {
|
if( circleCloseButton.isSelected() ) {
|
||||||
UIManager.put( "TabbedPane.closeArc", 999 );
|
UIManager.put( "TabbedPane.closeArc", 999 );
|
||||||
UIManager.put( "TabbedPane.closeCrossFilledSize", 5.5f );
|
UIManager.put( "TabbedPane.closeCrossFilledSize", 5.5f );
|
||||||
@@ -313,14 +313,6 @@ class TabsPanel
|
|||||||
putTabbedPanesClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
|
putTabbedPanesClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tabRotationChanged() {
|
|
||||||
String tabRotation = rotationAutoButton.isSelected() ? TABBED_PANE_TAB_ROTATION_AUTO
|
|
||||||
: rotationLeftButton.isSelected() ? TABBED_PANE_TAB_ROTATION_LEFT
|
|
||||||
: rotationRightButton.isSelected() ? TABBED_PANE_TAB_ROTATION_RIGHT
|
|
||||||
: null;
|
|
||||||
putTabbedPanesClientProperty( TABBED_PANE_TAB_ROTATION, tabRotation );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void putTabbedPanesClientProperty( String key, Object value ) {
|
private void putTabbedPanesClientProperty( String key, Object value ) {
|
||||||
updateTabbedPanesRecur( this, tabbedPane -> tabbedPane.putClientProperty( key, value ) );
|
updateTabbedPanesRecur( this, tabbedPane -> tabbedPane.putClientProperty( key, value ) );
|
||||||
}
|
}
|
||||||
@@ -339,8 +331,6 @@ class TabsPanel
|
|||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
JScrollPane tabsScrollPane = new JScrollPane();
|
|
||||||
ScrollablePanel panel6 = new ScrollablePanel();
|
|
||||||
JPanel panel1 = new JPanel();
|
JPanel panel1 = new JPanel();
|
||||||
JLabel tabPlacementLabel = new JLabel();
|
JLabel tabPlacementLabel = new JLabel();
|
||||||
tabPlacementToolBar = new JToolBar();
|
tabPlacementToolBar = new JToolBar();
|
||||||
@@ -407,369 +397,344 @@ class TabsPanel
|
|||||||
scrollAsNeededSingleButton = new JToggleButton();
|
scrollAsNeededSingleButton = new JToggleButton();
|
||||||
scrollAsNeededButton = new JToggleButton();
|
scrollAsNeededButton = new JToggleButton();
|
||||||
scrollNeverButton = new JToggleButton();
|
scrollNeverButton = new JToggleButton();
|
||||||
tabsPopupPolicyLabel = new JLabel();
|
|
||||||
tabsPopupPolicyToolBar = new JToolBar();
|
|
||||||
popupAsNeededButton = new JToggleButton();
|
|
||||||
popupNeverButton = new JToggleButton();
|
|
||||||
showTabSeparatorsCheckBox = new JCheckBox();
|
|
||||||
scrollButtonsPlacementLabel = new JLabel();
|
scrollButtonsPlacementLabel = new JLabel();
|
||||||
scrollButtonsPlacementToolBar = new JToolBar();
|
scrollButtonsPlacementToolBar = new JToolBar();
|
||||||
scrollBothButton = new JToggleButton();
|
scrollBothButton = new JToggleButton();
|
||||||
scrollTrailingButton = new JToggleButton();
|
scrollTrailingButton = new JToggleButton();
|
||||||
|
showTabSeparatorsCheckBox = new JCheckBox();
|
||||||
|
tabsPopupPolicyLabel = new JLabel();
|
||||||
|
tabsPopupPolicyToolBar = new JToolBar();
|
||||||
|
popupAsNeededButton = new JToggleButton();
|
||||||
|
popupNeverButton = new JToggleButton();
|
||||||
tabTypeLabel = new JLabel();
|
tabTypeLabel = new JLabel();
|
||||||
tabTypeToolBar = new JToolBar();
|
tabTypeToolBar = new JToolBar();
|
||||||
underlinedTabTypeButton = new JToggleButton();
|
underlinedTabTypeButton = new JToggleButton();
|
||||||
cardTabTypeButton = new JToggleButton();
|
cardTabTypeButton = new JToggleButton();
|
||||||
tabRotationLabel = new JLabel();
|
|
||||||
tabRotationToolBar = new JToolBar();
|
|
||||||
rotationNoneButton = new JToggleButton();
|
|
||||||
rotationAutoButton = new JToggleButton();
|
|
||||||
rotationLeftButton = new JToggleButton();
|
|
||||||
rotationRightButton = new JToggleButton();
|
|
||||||
|
|
||||||
//======== this ========
|
//======== this ========
|
||||||
setLayout(new MigLayout(
|
setLayout(new MigLayout(
|
||||||
"insets 0,hidemode 3",
|
"insets dialog,hidemode 3",
|
||||||
// columns
|
// columns
|
||||||
"[grow,fill]",
|
"[grow,fill]para" +
|
||||||
|
"[fill]para" +
|
||||||
|
"[fill]",
|
||||||
// rows
|
// rows
|
||||||
"[grow,fill]0" +
|
"[grow,fill]para" +
|
||||||
"[]0" +
|
"[]" +
|
||||||
"[]"));
|
"[]"));
|
||||||
|
|
||||||
//======== tabsScrollPane ========
|
//======== panel1 ========
|
||||||
{
|
{
|
||||||
tabsScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
panel1.setLayout(new MigLayout(
|
||||||
|
"insets 0,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[grow,fill]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[fill]para" +
|
||||||
|
"[]0" +
|
||||||
|
"[]" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
//======== panel6 ========
|
//---- tabPlacementLabel ----
|
||||||
|
tabPlacementLabel.setText("Tab placement");
|
||||||
|
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel1.add(tabPlacementLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//======== tabPlacementToolBar ========
|
||||||
{
|
{
|
||||||
panel6.setLayout(new MigLayout(
|
tabPlacementToolBar.setFloatable(false);
|
||||||
"insets dialog,hidemode 3",
|
tabPlacementToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
//---- topPlacementButton ----
|
||||||
|
topPlacementButton.setText("top");
|
||||||
|
topPlacementButton.setSelected(true);
|
||||||
|
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
topPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||||
|
tabPlacementToolBar.add(topPlacementButton);
|
||||||
|
|
||||||
|
//---- bottomPlacementButton ----
|
||||||
|
bottomPlacementButton.setText("bottom");
|
||||||
|
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||||
|
tabPlacementToolBar.add(bottomPlacementButton);
|
||||||
|
|
||||||
|
//---- leftPlacementButton ----
|
||||||
|
leftPlacementButton.setText("left");
|
||||||
|
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
leftPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||||
|
tabPlacementToolBar.add(leftPlacementButton);
|
||||||
|
|
||||||
|
//---- rightPlacementButton ----
|
||||||
|
rightPlacementButton.setText("right");
|
||||||
|
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
rightPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||||
|
tabPlacementToolBar.add(rightPlacementButton);
|
||||||
|
tabPlacementToolBar.addSeparator();
|
||||||
|
|
||||||
|
//---- scrollButton ----
|
||||||
|
scrollButton.setText("scroll");
|
||||||
|
scrollButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
scrollButton.addActionListener(e -> scrollChanged());
|
||||||
|
tabPlacementToolBar.add(scrollButton);
|
||||||
|
|
||||||
|
//---- borderButton ----
|
||||||
|
borderButton.setText("border");
|
||||||
|
borderButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
borderButton.addActionListener(e -> borderChanged());
|
||||||
|
tabPlacementToolBar.add(borderButton);
|
||||||
|
}
|
||||||
|
panel1.add(tabPlacementToolBar, "cell 0 0,alignx right,growx 0");
|
||||||
|
panel1.add(tabPlacementTabbedPane, "cell 0 1,width 300:300,height 100:100");
|
||||||
|
|
||||||
|
//---- tabLayoutLabel ----
|
||||||
|
tabLayoutLabel.setText("Tab layout");
|
||||||
|
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel1.add(tabLayoutLabel, "cell 0 2");
|
||||||
|
|
||||||
|
//======== tabLayoutToolBar ========
|
||||||
|
{
|
||||||
|
tabLayoutToolBar.setFloatable(false);
|
||||||
|
tabLayoutToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
//---- scrollTabLayoutButton ----
|
||||||
|
scrollTabLayoutButton.setText("scroll");
|
||||||
|
scrollTabLayoutButton.setSelected(true);
|
||||||
|
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||||
|
tabLayoutToolBar.add(scrollTabLayoutButton);
|
||||||
|
|
||||||
|
//---- wrapTabLayoutButton ----
|
||||||
|
wrapTabLayoutButton.setText("wrap");
|
||||||
|
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||||
|
tabLayoutToolBar.add(wrapTabLayoutButton);
|
||||||
|
}
|
||||||
|
panel1.add(tabLayoutToolBar, "cell 0 2,alignx right,growx 0");
|
||||||
|
|
||||||
|
//---- scrollLayoutNoteLabel ----
|
||||||
|
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
|
||||||
|
scrollLayoutNoteLabel.setEnabled(false);
|
||||||
|
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel1.add(scrollLayoutNoteLabel, "cell 0 3");
|
||||||
|
|
||||||
|
//---- wrapLayoutNoteLabel ----
|
||||||
|
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
|
||||||
|
wrapLayoutNoteLabel.setEnabled(false);
|
||||||
|
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel1.add(wrapLayoutNoteLabel, "cell 0 3");
|
||||||
|
panel1.add(scrollLayoutTabbedPane, "cell 0 4");
|
||||||
|
panel1.add(wrapLayoutTabbedPane, "cell 0 4,width 100:100,height pref*2px");
|
||||||
|
|
||||||
|
//---- closableTabsLabel ----
|
||||||
|
closableTabsLabel.setText("Closable tabs");
|
||||||
|
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel1.add(closableTabsLabel, "cell 0 5");
|
||||||
|
|
||||||
|
//======== closableTabsToolBar ========
|
||||||
|
{
|
||||||
|
closableTabsToolBar.setFloatable(false);
|
||||||
|
closableTabsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
//---- squareCloseButton ----
|
||||||
|
squareCloseButton.setText("square");
|
||||||
|
squareCloseButton.setSelected(true);
|
||||||
|
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||||
|
closableTabsToolBar.add(squareCloseButton);
|
||||||
|
|
||||||
|
//---- circleCloseButton ----
|
||||||
|
circleCloseButton.setText("circle");
|
||||||
|
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||||
|
closableTabsToolBar.add(circleCloseButton);
|
||||||
|
|
||||||
|
//---- redCrossCloseButton ----
|
||||||
|
redCrossCloseButton.setText("red cross");
|
||||||
|
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||||
|
closableTabsToolBar.add(redCrossCloseButton);
|
||||||
|
}
|
||||||
|
panel1.add(closableTabsToolBar, "cell 0 5,alignx right,growx 0");
|
||||||
|
panel1.add(closableTabsTabbedPane, "cell 0 6");
|
||||||
|
|
||||||
|
//---- tabAreaComponentsLabel ----
|
||||||
|
tabAreaComponentsLabel.setText("Custom tab area components");
|
||||||
|
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel1.add(tabAreaComponentsLabel, "cell 0 7");
|
||||||
|
|
||||||
|
//======== tabAreaComponentsToolBar ========
|
||||||
|
{
|
||||||
|
tabAreaComponentsToolBar.setFloatable(false);
|
||||||
|
tabAreaComponentsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
//---- leadingComponentButton ----
|
||||||
|
leadingComponentButton.setText("leading");
|
||||||
|
leadingComponentButton.setSelected(true);
|
||||||
|
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
leadingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||||
|
tabAreaComponentsToolBar.add(leadingComponentButton);
|
||||||
|
|
||||||
|
//---- trailingComponentButton ----
|
||||||
|
trailingComponentButton.setText("trailing");
|
||||||
|
trailingComponentButton.setSelected(true);
|
||||||
|
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
trailingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||||
|
tabAreaComponentsToolBar.add(trailingComponentButton);
|
||||||
|
}
|
||||||
|
panel1.add(tabAreaComponentsToolBar, "cell 0 7,alignx right,growx 0");
|
||||||
|
panel1.add(customComponentsTabbedPane, "cell 0 8");
|
||||||
|
}
|
||||||
|
add(panel1, "cell 0 0");
|
||||||
|
|
||||||
|
//======== panel2 ========
|
||||||
|
{
|
||||||
|
panel2.setLayout(new MigLayout(
|
||||||
|
"insets 0,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[grow,fill]",
|
||||||
|
// rows
|
||||||
|
"[]0" +
|
||||||
|
"[]" +
|
||||||
|
"[fill]" +
|
||||||
|
"[center]" +
|
||||||
|
"[center]" +
|
||||||
|
"[center]para" +
|
||||||
|
"[center]0" +
|
||||||
|
"[]" +
|
||||||
|
"[center]" +
|
||||||
|
"[center]" +
|
||||||
|
"[center]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- tabIconPlacementLabel ----
|
||||||
|
tabIconPlacementLabel.setText("Tab icon placement");
|
||||||
|
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel2.add(tabIconPlacementLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- tabIconPlacementNodeLabel ----
|
||||||
|
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
|
||||||
|
tabIconPlacementNodeLabel.setEnabled(false);
|
||||||
|
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
|
||||||
|
panel2.add(iconTopTabbedPane, "cell 0 2");
|
||||||
|
panel2.add(iconBottomTabbedPane, "cell 0 3");
|
||||||
|
panel2.add(iconLeadingTabbedPane, "cell 0 4");
|
||||||
|
panel2.add(iconTrailingTabbedPane, "cell 0 5");
|
||||||
|
|
||||||
|
//---- tabAreaAlignmentLabel ----
|
||||||
|
tabAreaAlignmentLabel.setText("Tab area alignment");
|
||||||
|
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel2.add(tabAreaAlignmentLabel, "cell 0 6");
|
||||||
|
|
||||||
|
//---- tabAreaAlignmentNoteLabel ----
|
||||||
|
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
|
||||||
|
tabAreaAlignmentNoteLabel.setEnabled(false);
|
||||||
|
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
|
||||||
|
panel2.add(alignLeadingTabbedPane, "cell 0 8");
|
||||||
|
panel2.add(alignCenterTabbedPane, "cell 0 9");
|
||||||
|
panel2.add(alignTrailingTabbedPane, "cell 0 10");
|
||||||
|
panel2.add(alignFillTabbedPane, "cell 0 11");
|
||||||
|
}
|
||||||
|
add(panel2, "cell 1 0,growy");
|
||||||
|
|
||||||
|
//======== panel3 ========
|
||||||
|
{
|
||||||
|
panel3.setLayout(new MigLayout(
|
||||||
|
"insets 0,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[grow,fill]",
|
||||||
|
// rows
|
||||||
|
"[]0" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]para" +
|
||||||
|
"[]0" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- tabWidthModeLabel ----
|
||||||
|
tabWidthModeLabel.setText("Tab width mode");
|
||||||
|
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel3.add(tabWidthModeLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- tabWidthModeNoteLabel ----
|
||||||
|
tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
|
||||||
|
tabWidthModeNoteLabel.setEnabled(false);
|
||||||
|
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel3.add(tabWidthModeNoteLabel, "cell 0 1");
|
||||||
|
panel3.add(widthPreferredTabbedPane, "cell 0 2");
|
||||||
|
panel3.add(widthEqualTabbedPane, "cell 0 3");
|
||||||
|
panel3.add(widthCompactTabbedPane, "cell 0 4");
|
||||||
|
|
||||||
|
//---- minMaxTabWidthLabel ----
|
||||||
|
minMaxTabWidthLabel.setText("Minimum/maximum tab width");
|
||||||
|
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel3.add(minMaxTabWidthLabel, "cell 0 5");
|
||||||
|
panel3.add(minimumTabWidthTabbedPane, "cell 0 6");
|
||||||
|
panel3.add(maximumTabWidthTabbedPane, "cell 0 7");
|
||||||
|
|
||||||
|
//---- tabAlignmentLabel ----
|
||||||
|
tabAlignmentLabel.setText("Tab title alignment");
|
||||||
|
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||||
|
panel3.add(tabAlignmentLabel, "cell 0 8");
|
||||||
|
|
||||||
|
//======== panel5 ========
|
||||||
|
{
|
||||||
|
panel5.setLayout(new MigLayout(
|
||||||
|
"insets 0,hidemode 3",
|
||||||
// columns
|
// columns
|
||||||
"[grow,fill]para" +
|
"[grow,fill]para" +
|
||||||
"[fill]para" +
|
|
||||||
"[fill]",
|
"[fill]",
|
||||||
// rows
|
// rows
|
||||||
"[grow,fill]"));
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
//======== panel1 ========
|
//---- tabAlignmentNoteLabel ----
|
||||||
|
tabAlignmentNoteLabel.setText("(leading/center/trailing)");
|
||||||
|
tabAlignmentNoteLabel.setEnabled(false);
|
||||||
|
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel5.add(tabAlignmentNoteLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- tabAlignmentNoteLabel2 ----
|
||||||
|
tabAlignmentNoteLabel2.setText("(trailing)");
|
||||||
|
tabAlignmentNoteLabel2.setEnabled(false);
|
||||||
|
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
|
||||||
|
panel5.add(tabAlignLeadingTabbedPane, "cell 0 1");
|
||||||
|
|
||||||
|
//======== tabAlignVerticalTabbedPane ========
|
||||||
{
|
{
|
||||||
panel1.setLayout(new MigLayout(
|
tabAlignVerticalTabbedPane.setTabPlacement(SwingConstants.LEFT);
|
||||||
"insets 0,hidemode 3",
|
|
||||||
// columns
|
|
||||||
"[grow,fill]",
|
|
||||||
// rows
|
|
||||||
"[]" +
|
|
||||||
"[fill]para" +
|
|
||||||
"[]0" +
|
|
||||||
"[]" +
|
|
||||||
"[]para" +
|
|
||||||
"[]" +
|
|
||||||
"[]para" +
|
|
||||||
"[]" +
|
|
||||||
"[]"));
|
|
||||||
|
|
||||||
//---- tabPlacementLabel ----
|
|
||||||
tabPlacementLabel.setText("Tab placement");
|
|
||||||
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel1.add(tabPlacementLabel, "cell 0 0");
|
|
||||||
|
|
||||||
//======== tabPlacementToolBar ========
|
|
||||||
{
|
|
||||||
tabPlacementToolBar.setFloatable(false);
|
|
||||||
tabPlacementToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- topPlacementButton ----
|
|
||||||
topPlacementButton.setText("top");
|
|
||||||
topPlacementButton.setSelected(true);
|
|
||||||
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
topPlacementButton.addActionListener(e -> tabPlacementChanged());
|
|
||||||
tabPlacementToolBar.add(topPlacementButton);
|
|
||||||
|
|
||||||
//---- bottomPlacementButton ----
|
|
||||||
bottomPlacementButton.setText("bottom");
|
|
||||||
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
|
|
||||||
tabPlacementToolBar.add(bottomPlacementButton);
|
|
||||||
|
|
||||||
//---- leftPlacementButton ----
|
|
||||||
leftPlacementButton.setText("left");
|
|
||||||
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
leftPlacementButton.addActionListener(e -> tabPlacementChanged());
|
|
||||||
tabPlacementToolBar.add(leftPlacementButton);
|
|
||||||
|
|
||||||
//---- rightPlacementButton ----
|
|
||||||
rightPlacementButton.setText("right");
|
|
||||||
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
rightPlacementButton.addActionListener(e -> tabPlacementChanged());
|
|
||||||
tabPlacementToolBar.add(rightPlacementButton);
|
|
||||||
tabPlacementToolBar.addSeparator();
|
|
||||||
|
|
||||||
//---- scrollButton ----
|
|
||||||
scrollButton.setText("scroll");
|
|
||||||
scrollButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
scrollButton.addActionListener(e -> scrollChanged());
|
|
||||||
tabPlacementToolBar.add(scrollButton);
|
|
||||||
|
|
||||||
//---- borderButton ----
|
|
||||||
borderButton.setText("border");
|
|
||||||
borderButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
borderButton.addActionListener(e -> borderChanged());
|
|
||||||
tabPlacementToolBar.add(borderButton);
|
|
||||||
}
|
|
||||||
panel1.add(tabPlacementToolBar, "cell 0 0,alignx right,growx 0");
|
|
||||||
panel1.add(tabPlacementTabbedPane, "cell 0 1,width 300:300,height 100:100");
|
|
||||||
|
|
||||||
//---- tabLayoutLabel ----
|
|
||||||
tabLayoutLabel.setText("Tab layout");
|
|
||||||
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel1.add(tabLayoutLabel, "cell 0 2");
|
|
||||||
|
|
||||||
//======== tabLayoutToolBar ========
|
|
||||||
{
|
|
||||||
tabLayoutToolBar.setFloatable(false);
|
|
||||||
tabLayoutToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- scrollTabLayoutButton ----
|
|
||||||
scrollTabLayoutButton.setText("scroll");
|
|
||||||
scrollTabLayoutButton.setSelected(true);
|
|
||||||
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
|
||||||
tabLayoutToolBar.add(scrollTabLayoutButton);
|
|
||||||
|
|
||||||
//---- wrapTabLayoutButton ----
|
|
||||||
wrapTabLayoutButton.setText("wrap");
|
|
||||||
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
|
||||||
tabLayoutToolBar.add(wrapTabLayoutButton);
|
|
||||||
}
|
|
||||||
panel1.add(tabLayoutToolBar, "cell 0 2,alignx right,growx 0");
|
|
||||||
|
|
||||||
//---- scrollLayoutNoteLabel ----
|
|
||||||
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
|
|
||||||
scrollLayoutNoteLabel.setEnabled(false);
|
|
||||||
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel1.add(scrollLayoutNoteLabel, "cell 0 3");
|
|
||||||
|
|
||||||
//---- wrapLayoutNoteLabel ----
|
|
||||||
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
|
|
||||||
wrapLayoutNoteLabel.setEnabled(false);
|
|
||||||
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel1.add(wrapLayoutNoteLabel, "cell 0 3");
|
|
||||||
panel1.add(scrollLayoutTabbedPane, "cell 0 4");
|
|
||||||
panel1.add(wrapLayoutTabbedPane, "cell 0 4,width 100:100,height pref*2px");
|
|
||||||
|
|
||||||
//---- closableTabsLabel ----
|
|
||||||
closableTabsLabel.setText("Closable tabs");
|
|
||||||
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel1.add(closableTabsLabel, "cell 0 5");
|
|
||||||
|
|
||||||
//======== closableTabsToolBar ========
|
|
||||||
{
|
|
||||||
closableTabsToolBar.setFloatable(false);
|
|
||||||
closableTabsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- squareCloseButton ----
|
|
||||||
squareCloseButton.setText("square");
|
|
||||||
squareCloseButton.setSelected(true);
|
|
||||||
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
|
||||||
closableTabsToolBar.add(squareCloseButton);
|
|
||||||
|
|
||||||
//---- circleCloseButton ----
|
|
||||||
circleCloseButton.setText("circle");
|
|
||||||
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
|
||||||
closableTabsToolBar.add(circleCloseButton);
|
|
||||||
|
|
||||||
//---- redCrossCloseButton ----
|
|
||||||
redCrossCloseButton.setText("red cross");
|
|
||||||
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
|
||||||
closableTabsToolBar.add(redCrossCloseButton);
|
|
||||||
}
|
|
||||||
panel1.add(closableTabsToolBar, "cell 0 5,alignx right,growx 0");
|
|
||||||
panel1.add(closableTabsTabbedPane, "cell 0 6");
|
|
||||||
|
|
||||||
//---- tabAreaComponentsLabel ----
|
|
||||||
tabAreaComponentsLabel.setText("Custom tab area components");
|
|
||||||
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel1.add(tabAreaComponentsLabel, "cell 0 7");
|
|
||||||
|
|
||||||
//======== tabAreaComponentsToolBar ========
|
|
||||||
{
|
|
||||||
tabAreaComponentsToolBar.setFloatable(false);
|
|
||||||
tabAreaComponentsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- leadingComponentButton ----
|
|
||||||
leadingComponentButton.setText("leading");
|
|
||||||
leadingComponentButton.setSelected(true);
|
|
||||||
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
leadingComponentButton.addActionListener(e -> customComponentsChanged());
|
|
||||||
tabAreaComponentsToolBar.add(leadingComponentButton);
|
|
||||||
|
|
||||||
//---- trailingComponentButton ----
|
|
||||||
trailingComponentButton.setText("trailing");
|
|
||||||
trailingComponentButton.setSelected(true);
|
|
||||||
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
trailingComponentButton.addActionListener(e -> customComponentsChanged());
|
|
||||||
tabAreaComponentsToolBar.add(trailingComponentButton);
|
|
||||||
}
|
|
||||||
panel1.add(tabAreaComponentsToolBar, "cell 0 7,alignx right,growx 0");
|
|
||||||
panel1.add(customComponentsTabbedPane, "cell 0 8");
|
|
||||||
}
|
}
|
||||||
panel6.add(panel1, "cell 0 0");
|
panel5.add(tabAlignVerticalTabbedPane, "cell 1 1 1 3,growy");
|
||||||
|
panel5.add(tabAlignCenterTabbedPane, "cell 0 2");
|
||||||
//======== panel2 ========
|
panel5.add(tabAlignTrailingTabbedPane, "cell 0 3");
|
||||||
{
|
|
||||||
panel2.setLayout(new MigLayout(
|
|
||||||
"insets 0,hidemode 3",
|
|
||||||
// columns
|
|
||||||
"[grow,fill]",
|
|
||||||
// rows
|
|
||||||
"[]0" +
|
|
||||||
"[]" +
|
|
||||||
"[fill]" +
|
|
||||||
"[center]" +
|
|
||||||
"[center]" +
|
|
||||||
"[center]para" +
|
|
||||||
"[center]0" +
|
|
||||||
"[]" +
|
|
||||||
"[center]" +
|
|
||||||
"[center]" +
|
|
||||||
"[center]" +
|
|
||||||
"[]"));
|
|
||||||
|
|
||||||
//---- tabIconPlacementLabel ----
|
|
||||||
tabIconPlacementLabel.setText("Tab icon placement");
|
|
||||||
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel2.add(tabIconPlacementLabel, "cell 0 0");
|
|
||||||
|
|
||||||
//---- tabIconPlacementNodeLabel ----
|
|
||||||
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
|
|
||||||
tabIconPlacementNodeLabel.setEnabled(false);
|
|
||||||
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
|
|
||||||
panel2.add(iconTopTabbedPane, "cell 0 2");
|
|
||||||
panel2.add(iconBottomTabbedPane, "cell 0 3");
|
|
||||||
panel2.add(iconLeadingTabbedPane, "cell 0 4");
|
|
||||||
panel2.add(iconTrailingTabbedPane, "cell 0 5");
|
|
||||||
|
|
||||||
//---- tabAreaAlignmentLabel ----
|
|
||||||
tabAreaAlignmentLabel.setText("Tab area alignment");
|
|
||||||
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel2.add(tabAreaAlignmentLabel, "cell 0 6");
|
|
||||||
|
|
||||||
//---- tabAreaAlignmentNoteLabel ----
|
|
||||||
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
|
|
||||||
tabAreaAlignmentNoteLabel.setEnabled(false);
|
|
||||||
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
|
|
||||||
panel2.add(alignLeadingTabbedPane, "cell 0 8");
|
|
||||||
panel2.add(alignCenterTabbedPane, "cell 0 9");
|
|
||||||
panel2.add(alignTrailingTabbedPane, "cell 0 10");
|
|
||||||
panel2.add(alignFillTabbedPane, "cell 0 11");
|
|
||||||
}
|
|
||||||
panel6.add(panel2, "cell 1 0,growy");
|
|
||||||
|
|
||||||
//======== panel3 ========
|
|
||||||
{
|
|
||||||
panel3.setLayout(new MigLayout(
|
|
||||||
"insets 0,hidemode 3",
|
|
||||||
// columns
|
|
||||||
"[grow,fill]",
|
|
||||||
// rows
|
|
||||||
"[]0" +
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]para" +
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]para" +
|
|
||||||
"[]0" +
|
|
||||||
"[]"));
|
|
||||||
|
|
||||||
//---- tabWidthModeLabel ----
|
|
||||||
tabWidthModeLabel.setText("Tab width mode");
|
|
||||||
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel3.add(tabWidthModeLabel, "cell 0 0");
|
|
||||||
|
|
||||||
//---- tabWidthModeNoteLabel ----
|
|
||||||
tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
|
|
||||||
tabWidthModeNoteLabel.setEnabled(false);
|
|
||||||
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel3.add(tabWidthModeNoteLabel, "cell 0 1");
|
|
||||||
panel3.add(widthPreferredTabbedPane, "cell 0 2");
|
|
||||||
panel3.add(widthEqualTabbedPane, "cell 0 3");
|
|
||||||
panel3.add(widthCompactTabbedPane, "cell 0 4");
|
|
||||||
|
|
||||||
//---- minMaxTabWidthLabel ----
|
|
||||||
minMaxTabWidthLabel.setText("Minimum/maximum tab width");
|
|
||||||
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel3.add(minMaxTabWidthLabel, "cell 0 5");
|
|
||||||
panel3.add(minimumTabWidthTabbedPane, "cell 0 6");
|
|
||||||
panel3.add(maximumTabWidthTabbedPane, "cell 0 7");
|
|
||||||
|
|
||||||
//---- tabAlignmentLabel ----
|
|
||||||
tabAlignmentLabel.setText("Tab title alignment");
|
|
||||||
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
|
||||||
panel3.add(tabAlignmentLabel, "cell 0 8");
|
|
||||||
|
|
||||||
//======== panel5 ========
|
|
||||||
{
|
|
||||||
panel5.setLayout(new MigLayout(
|
|
||||||
"insets 0,hidemode 3",
|
|
||||||
// columns
|
|
||||||
"[grow,fill]para" +
|
|
||||||
"[fill]",
|
|
||||||
// rows
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]" +
|
|
||||||
"[]"));
|
|
||||||
|
|
||||||
//---- tabAlignmentNoteLabel ----
|
|
||||||
tabAlignmentNoteLabel.setText("(leading/center/trailing)");
|
|
||||||
tabAlignmentNoteLabel.setEnabled(false);
|
|
||||||
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel5.add(tabAlignmentNoteLabel, "cell 0 0");
|
|
||||||
|
|
||||||
//---- tabAlignmentNoteLabel2 ----
|
|
||||||
tabAlignmentNoteLabel2.setText("(trailing)");
|
|
||||||
tabAlignmentNoteLabel2.setEnabled(false);
|
|
||||||
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
|
|
||||||
panel5.add(tabAlignLeadingTabbedPane, "cell 0 1");
|
|
||||||
|
|
||||||
//======== tabAlignVerticalTabbedPane ========
|
|
||||||
{
|
|
||||||
tabAlignVerticalTabbedPane.setTabPlacement(SwingConstants.LEFT);
|
|
||||||
}
|
|
||||||
panel5.add(tabAlignVerticalTabbedPane, "cell 1 1 1 4,growy");
|
|
||||||
panel5.add(tabAlignCenterTabbedPane, "cell 0 2");
|
|
||||||
panel5.add(tabAlignTrailingTabbedPane, "cell 0 3");
|
|
||||||
}
|
|
||||||
panel3.add(panel5, "cell 0 9");
|
|
||||||
}
|
|
||||||
panel6.add(panel3, "cell 2 0");
|
|
||||||
}
|
}
|
||||||
tabsScrollPane.setViewportView(panel6);
|
panel3.add(panel5, "cell 0 9");
|
||||||
}
|
}
|
||||||
add(tabsScrollPane, "cell 0 0");
|
add(panel3, "cell 2 0");
|
||||||
add(separator2, "cell 0 1");
|
add(separator2, "cell 0 1 3 1");
|
||||||
|
|
||||||
//======== panel4 ========
|
//======== panel4 ========
|
||||||
{
|
{
|
||||||
panel4.setLayout(new MigLayout(
|
panel4.setLayout(new MigLayout(
|
||||||
"insets panel,hidemode 3",
|
"insets 0,hidemode 3",
|
||||||
// columns
|
// columns
|
||||||
"[]" +
|
"[]" +
|
||||||
"[fill]para" +
|
"[fill]para" +
|
||||||
"[fill]" +
|
"[fill]" +
|
||||||
"[fill]para" +
|
"[fill]para" +
|
||||||
"[fill]" +
|
|
||||||
"[fill]",
|
"[fill]",
|
||||||
// rows
|
// rows
|
||||||
"[]" +
|
"[]" +
|
||||||
@@ -805,38 +770,9 @@ class TabsPanel
|
|||||||
}
|
}
|
||||||
panel4.add(scrollButtonsPolicyToolBar, "cell 1 0");
|
panel4.add(scrollButtonsPolicyToolBar, "cell 1 0");
|
||||||
|
|
||||||
//---- tabsPopupPolicyLabel ----
|
|
||||||
tabsPopupPolicyLabel.setText("Tabs popup policy:");
|
|
||||||
panel4.add(tabsPopupPolicyLabel, "cell 2 0");
|
|
||||||
|
|
||||||
//======== tabsPopupPolicyToolBar ========
|
|
||||||
{
|
|
||||||
tabsPopupPolicyToolBar.setFloatable(false);
|
|
||||||
tabsPopupPolicyToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- popupAsNeededButton ----
|
|
||||||
popupAsNeededButton.setText("asNeeded");
|
|
||||||
popupAsNeededButton.setSelected(true);
|
|
||||||
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
|
|
||||||
tabsPopupPolicyToolBar.add(popupAsNeededButton);
|
|
||||||
|
|
||||||
//---- popupNeverButton ----
|
|
||||||
popupNeverButton.setText("never");
|
|
||||||
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
|
|
||||||
tabsPopupPolicyToolBar.add(popupNeverButton);
|
|
||||||
}
|
|
||||||
panel4.add(tabsPopupPolicyToolBar, "cell 3 0");
|
|
||||||
|
|
||||||
//---- showTabSeparatorsCheckBox ----
|
|
||||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
|
||||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
|
||||||
panel4.add(showTabSeparatorsCheckBox, "cell 4 0 2 1,alignx left,growx 0");
|
|
||||||
|
|
||||||
//---- scrollButtonsPlacementLabel ----
|
//---- scrollButtonsPlacementLabel ----
|
||||||
scrollButtonsPlacementLabel.setText("Scroll buttons placement:");
|
scrollButtonsPlacementLabel.setText("Scroll buttons placement:");
|
||||||
panel4.add(scrollButtonsPlacementLabel, "cell 0 1");
|
panel4.add(scrollButtonsPlacementLabel, "cell 2 0");
|
||||||
|
|
||||||
//======== scrollButtonsPlacementToolBar ========
|
//======== scrollButtonsPlacementToolBar ========
|
||||||
{
|
{
|
||||||
@@ -856,7 +792,36 @@ class TabsPanel
|
|||||||
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||||
scrollButtonsPlacementToolBar.add(scrollTrailingButton);
|
scrollButtonsPlacementToolBar.add(scrollTrailingButton);
|
||||||
}
|
}
|
||||||
panel4.add(scrollButtonsPlacementToolBar, "cell 1 1");
|
panel4.add(scrollButtonsPlacementToolBar, "cell 3 0");
|
||||||
|
|
||||||
|
//---- showTabSeparatorsCheckBox ----
|
||||||
|
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||||
|
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||||
|
panel4.add(showTabSeparatorsCheckBox, "cell 4 0");
|
||||||
|
|
||||||
|
//---- tabsPopupPolicyLabel ----
|
||||||
|
tabsPopupPolicyLabel.setText("Tabs popup policy:");
|
||||||
|
panel4.add(tabsPopupPolicyLabel, "cell 0 1");
|
||||||
|
|
||||||
|
//======== tabsPopupPolicyToolBar ========
|
||||||
|
{
|
||||||
|
tabsPopupPolicyToolBar.setFloatable(false);
|
||||||
|
tabsPopupPolicyToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
//---- popupAsNeededButton ----
|
||||||
|
popupAsNeededButton.setText("asNeeded");
|
||||||
|
popupAsNeededButton.setSelected(true);
|
||||||
|
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||||
|
tabsPopupPolicyToolBar.add(popupAsNeededButton);
|
||||||
|
|
||||||
|
//---- popupNeverButton ----
|
||||||
|
popupNeverButton.setText("never");
|
||||||
|
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||||
|
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||||
|
tabsPopupPolicyToolBar.add(popupNeverButton);
|
||||||
|
}
|
||||||
|
panel4.add(tabsPopupPolicyToolBar, "cell 1 1");
|
||||||
|
|
||||||
//---- tabTypeLabel ----
|
//---- tabTypeLabel ----
|
||||||
tabTypeLabel.setText("Tab type:");
|
tabTypeLabel.setText("Tab type:");
|
||||||
@@ -880,44 +845,8 @@ class TabsPanel
|
|||||||
tabTypeToolBar.add(cardTabTypeButton);
|
tabTypeToolBar.add(cardTabTypeButton);
|
||||||
}
|
}
|
||||||
panel4.add(tabTypeToolBar, "cell 3 1");
|
panel4.add(tabTypeToolBar, "cell 3 1");
|
||||||
|
|
||||||
//---- tabRotationLabel ----
|
|
||||||
tabRotationLabel.setText("Tab rotation:");
|
|
||||||
panel4.add(tabRotationLabel, "cell 4 1");
|
|
||||||
|
|
||||||
//======== tabRotationToolBar ========
|
|
||||||
{
|
|
||||||
tabRotationToolBar.setFloatable(false);
|
|
||||||
tabRotationToolBar.setBorder(BorderFactory.createEmptyBorder());
|
|
||||||
|
|
||||||
//---- rotationNoneButton ----
|
|
||||||
rotationNoneButton.setText("none");
|
|
||||||
rotationNoneButton.setSelected(true);
|
|
||||||
rotationNoneButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
rotationNoneButton.addActionListener(e -> tabRotationChanged());
|
|
||||||
tabRotationToolBar.add(rotationNoneButton);
|
|
||||||
|
|
||||||
//---- rotationAutoButton ----
|
|
||||||
rotationAutoButton.setText("auto");
|
|
||||||
rotationAutoButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
rotationAutoButton.addActionListener(e -> tabRotationChanged());
|
|
||||||
tabRotationToolBar.add(rotationAutoButton);
|
|
||||||
|
|
||||||
//---- rotationLeftButton ----
|
|
||||||
rotationLeftButton.setText("left");
|
|
||||||
rotationLeftButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
rotationLeftButton.addActionListener(e -> tabRotationChanged());
|
|
||||||
tabRotationToolBar.add(rotationLeftButton);
|
|
||||||
|
|
||||||
//---- rotationRightButton ----
|
|
||||||
rotationRightButton.setText("right");
|
|
||||||
rotationRightButton.putClientProperty("FlatLaf.styleClass", "small");
|
|
||||||
rotationRightButton.addActionListener(e -> tabRotationChanged());
|
|
||||||
tabRotationToolBar.add(rotationRightButton);
|
|
||||||
}
|
|
||||||
panel4.add(tabRotationToolBar, "cell 5 1");
|
|
||||||
}
|
}
|
||||||
add(panel4, "cell 0 2");
|
add(panel4, "cell 0 2 3 1");
|
||||||
|
|
||||||
//---- tabPlacementButtonGroup ----
|
//---- tabPlacementButtonGroup ----
|
||||||
ButtonGroup tabPlacementButtonGroup = new ButtonGroup();
|
ButtonGroup tabPlacementButtonGroup = new ButtonGroup();
|
||||||
@@ -943,27 +872,20 @@ class TabsPanel
|
|||||||
scrollButtonsPolicyButtonGroup.add(scrollAsNeededButton);
|
scrollButtonsPolicyButtonGroup.add(scrollAsNeededButton);
|
||||||
scrollButtonsPolicyButtonGroup.add(scrollNeverButton);
|
scrollButtonsPolicyButtonGroup.add(scrollNeverButton);
|
||||||
|
|
||||||
//---- tabsPopupPolicyButtonGroup ----
|
|
||||||
ButtonGroup tabsPopupPolicyButtonGroup = new ButtonGroup();
|
|
||||||
tabsPopupPolicyButtonGroup.add(popupAsNeededButton);
|
|
||||||
tabsPopupPolicyButtonGroup.add(popupNeverButton);
|
|
||||||
|
|
||||||
//---- scrollButtonsPlacementButtonGroup ----
|
//---- scrollButtonsPlacementButtonGroup ----
|
||||||
ButtonGroup scrollButtonsPlacementButtonGroup = new ButtonGroup();
|
ButtonGroup scrollButtonsPlacementButtonGroup = new ButtonGroup();
|
||||||
scrollButtonsPlacementButtonGroup.add(scrollBothButton);
|
scrollButtonsPlacementButtonGroup.add(scrollBothButton);
|
||||||
scrollButtonsPlacementButtonGroup.add(scrollTrailingButton);
|
scrollButtonsPlacementButtonGroup.add(scrollTrailingButton);
|
||||||
|
|
||||||
|
//---- tabsPopupPolicyButtonGroup ----
|
||||||
|
ButtonGroup tabsPopupPolicyButtonGroup = new ButtonGroup();
|
||||||
|
tabsPopupPolicyButtonGroup.add(popupAsNeededButton);
|
||||||
|
tabsPopupPolicyButtonGroup.add(popupNeverButton);
|
||||||
|
|
||||||
//---- tabTypeButtonGroup ----
|
//---- tabTypeButtonGroup ----
|
||||||
ButtonGroup tabTypeButtonGroup = new ButtonGroup();
|
ButtonGroup tabTypeButtonGroup = new ButtonGroup();
|
||||||
tabTypeButtonGroup.add(underlinedTabTypeButton);
|
tabTypeButtonGroup.add(underlinedTabTypeButton);
|
||||||
tabTypeButtonGroup.add(cardTabTypeButton);
|
tabTypeButtonGroup.add(cardTabTypeButton);
|
||||||
|
|
||||||
//---- tabRotationButtonGroup ----
|
|
||||||
ButtonGroup tabRotationButtonGroup = new ButtonGroup();
|
|
||||||
tabRotationButtonGroup.add(rotationNoneButton);
|
|
||||||
tabRotationButtonGroup.add(rotationAutoButton);
|
|
||||||
tabRotationButtonGroup.add(rotationLeftButton);
|
|
||||||
tabRotationButtonGroup.add(rotationRightButton);
|
|
||||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
|
||||||
if( FlatLafDemo.screenshotsMode ) {
|
if( FlatLafDemo.screenshotsMode ) {
|
||||||
@@ -1039,24 +961,18 @@ class TabsPanel
|
|||||||
private JToggleButton scrollAsNeededSingleButton;
|
private JToggleButton scrollAsNeededSingleButton;
|
||||||
private JToggleButton scrollAsNeededButton;
|
private JToggleButton scrollAsNeededButton;
|
||||||
private JToggleButton scrollNeverButton;
|
private JToggleButton scrollNeverButton;
|
||||||
private JLabel tabsPopupPolicyLabel;
|
|
||||||
private JToolBar tabsPopupPolicyToolBar;
|
|
||||||
private JToggleButton popupAsNeededButton;
|
|
||||||
private JToggleButton popupNeverButton;
|
|
||||||
private JCheckBox showTabSeparatorsCheckBox;
|
|
||||||
private JLabel scrollButtonsPlacementLabel;
|
private JLabel scrollButtonsPlacementLabel;
|
||||||
private JToolBar scrollButtonsPlacementToolBar;
|
private JToolBar scrollButtonsPlacementToolBar;
|
||||||
private JToggleButton scrollBothButton;
|
private JToggleButton scrollBothButton;
|
||||||
private JToggleButton scrollTrailingButton;
|
private JToggleButton scrollTrailingButton;
|
||||||
|
private JCheckBox showTabSeparatorsCheckBox;
|
||||||
|
private JLabel tabsPopupPolicyLabel;
|
||||||
|
private JToolBar tabsPopupPolicyToolBar;
|
||||||
|
private JToggleButton popupAsNeededButton;
|
||||||
|
private JToggleButton popupNeverButton;
|
||||||
private JLabel tabTypeLabel;
|
private JLabel tabTypeLabel;
|
||||||
private JToolBar tabTypeToolBar;
|
private JToolBar tabTypeToolBar;
|
||||||
private JToggleButton underlinedTabTypeButton;
|
private JToggleButton underlinedTabTypeButton;
|
||||||
private JToggleButton cardTabTypeButton;
|
private JToggleButton cardTabTypeButton;
|
||||||
private JLabel tabRotationLabel;
|
|
||||||
private JToolBar tabRotationToolBar;
|
|
||||||
private JToggleButton rotationNoneButton;
|
|
||||||
private JToggleButton rotationAutoButton;
|
|
||||||
private JToggleButton rotationLeftButton;
|
|
||||||
private JToggleButton rotationRightButton;
|
|
||||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ import java.awt.Window;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.event.WindowListener;
|
import java.awt.event.WindowListener;
|
||||||
|
import java.beans.Beans;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -156,6 +157,9 @@ public class IJThemesPanel
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateThemesList() {
|
private void updateThemesList() {
|
||||||
|
if( Beans.isDesignTime() )
|
||||||
|
return; // disable if running in GUI builder
|
||||||
|
|
||||||
int filterLightDark = filterComboBox.getSelectedIndex();
|
int filterLightDark = filterComboBox.getSelectedIndex();
|
||||||
boolean showLight = (filterLightDark != 2);
|
boolean showLight = (filterLightDark != 2);
|
||||||
boolean showDark = (filterLightDark != 1);
|
boolean showDark = (filterLightDark != 1);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ build script:
|
|||||||
artifactId: flatlaf-extras
|
artifactId: flatlaf-extras
|
||||||
version: (see button below)
|
version: (see button below)
|
||||||
|
|
||||||
Otherwise, download `flatlaf-extras-<version>.jar` here:
|
Otherwise download `flatlaf-extras-<version>.jar` here:
|
||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-extras)
|
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-extras)
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class FlatAnimatedLafChange
|
|||||||
* Invoke before setting new look and feel.
|
* Invoke before setting new look and feel.
|
||||||
*/
|
*/
|
||||||
public static void showSnapshot() {
|
public static void showSnapshot() {
|
||||||
if( !FlatSystemProperties.getBoolean( "flatlaf.animatedLafChange", true ) )
|
if( !Animator.useAnimation() || !FlatSystemProperties.getBoolean( "flatlaf.animatedLafChange", true ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// stop already running animation
|
// stop already running animation
|
||||||
@@ -133,12 +133,12 @@ public class FlatAnimatedLafChange
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts an animation that shows the snapshot (created by {@link #showSnapshot()})
|
* Starts an animation that shows the snapshot (created by {@link #showSnapshot()}
|
||||||
* with a decreasing alpha. At the end, the snapshot is removed and the new UI is shown.
|
* with an decreasing alpha. At the end, the snapshot is removed and the new UI is shown.
|
||||||
* Invoke after updating UI.
|
* Invoke after updating UI.
|
||||||
*/
|
*/
|
||||||
public static void hideSnapshotWithAnimation() {
|
public static void hideSnapshotWithAnimation() {
|
||||||
if( !FlatSystemProperties.getBoolean( "flatlaf.animatedLafChange", true ) )
|
if( !Animator.useAnimation() || !FlatSystemProperties.getBoolean( "flatlaf.animatedLafChange", true ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( oldUIsnapshots.isEmpty() )
|
if( oldUIsnapshots.isEmpty() )
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public class FlatDesktop
|
|||||||
(proxy, method, args) -> {
|
(proxy, method, args) -> {
|
||||||
// Use invokeLater to release the listener firing for the case
|
// Use invokeLater to release the listener firing for the case
|
||||||
// that the action listener shows a modal dialog.
|
// that the action listener shows a modal dialog.
|
||||||
// This (hopefully) prevents application hanging.
|
// This (hopefully) prevents application hunging.
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
handler.run();
|
handler.run();
|
||||||
} );
|
} );
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class FlatSVGIcon
|
|||||||
* in the tag {@code <svg>} are used as icon size.
|
* in the tag {@code <svg>} are used as icon size.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -106,7 +106,7 @@ public class FlatSVGIcon
|
|||||||
* in the tag {@code <svg>} are used as icon size.
|
* in the tag {@code <svg>} are used as icon size.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -124,7 +124,7 @@ public class FlatSVGIcon
|
|||||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -144,7 +144,7 @@ public class FlatSVGIcon
|
|||||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -166,7 +166,7 @@ public class FlatSVGIcon
|
|||||||
* by the given scale factor.
|
* by the given scale factor.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -187,7 +187,7 @@ public class FlatSVGIcon
|
|||||||
* by the given scale factor.
|
* by the given scale factor.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #FlatSVGIcon(URL)}.
|
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||||
* <p>
|
* <p>
|
||||||
* This is cheap operation because the icon is only loaded when used.
|
* This is cheap operation because the icon is only loaded when used.
|
||||||
*
|
*
|
||||||
@@ -259,7 +259,7 @@ public class FlatSVGIcon
|
|||||||
* <p>
|
* <p>
|
||||||
* The input stream is loaded, parsed and closed immediately.
|
* The input stream is loaded, parsed and closed immediately.
|
||||||
*
|
*
|
||||||
* @param in the input stream for reading an SVG resource
|
* @param in the input stream for reading a SVG resource
|
||||||
* @throws IOException if an I/O exception occurs
|
* @throws IOException if an I/O exception occurs
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ public class FlatSVGUtils
|
|||||||
* then a single multi-resolution image is returned that creates images on demand
|
* then a single multi-resolution image is returned that creates images on demand
|
||||||
* for requested sizes from SVG.
|
* for requested sizes from SVG.
|
||||||
* This has the advantage that only images for used sizes are created.
|
* This has the advantage that only images for used sizes are created.
|
||||||
* Also, if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #createWindowIconImages(URL)}.
|
* Otherwise use {@link #createWindowIconImages(URL)}.
|
||||||
*
|
*
|
||||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||||
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
||||||
@@ -69,7 +69,7 @@ public class FlatSVGUtils
|
|||||||
* then a single multi-resolution image is returned that creates images on demand
|
* then a single multi-resolution image is returned that creates images on demand
|
||||||
* for requested sizes from SVG.
|
* for requested sizes from SVG.
|
||||||
* This has the advantage that only images for used sizes are created.
|
* This has the advantage that only images for used sizes are created.
|
||||||
* Also, if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is useful if using Java modules and the package containing the SVG
|
* This method is useful if using Java modules and the package containing the SVG
|
||||||
* is not opened in {@code module-info.java}.
|
* is not opened in {@code module-info.java}.
|
||||||
@@ -92,7 +92,7 @@ public class FlatSVGUtils
|
|||||||
// any size is created on demand when
|
// any size is created on demand when
|
||||||
// MultiResolutionImage.getResolutionVariant(double destImageWidth, double destImageHeight)
|
// MultiResolutionImage.getResolutionVariant(double destImageWidth, double destImageHeight)
|
||||||
// is invoked.
|
// is invoked.
|
||||||
// These sizes are only used by MultiResolutionImage.getResolutionVariants().
|
// This sizes are only used by MultiResolutionImage.getResolutionVariants().
|
||||||
new Dimension( 16, 16 ), // 100%
|
new Dimension( 16, 16 ), // 100%
|
||||||
new Dimension( 20, 20 ), // 125%
|
new Dimension( 20, 20 ), // 125%
|
||||||
new Dimension( 24, 24 ), // 150%
|
new Dimension( 24, 24 ), // 150%
|
||||||
@@ -120,7 +120,7 @@ public class FlatSVGUtils
|
|||||||
* Creates a buffered image and renders the given SVG into it.
|
* Creates a buffered image and renders the given SVG into it.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #svg2image(URL, int, int)}.
|
* Otherwise use {@link #svg2image(URL, int, int)}.
|
||||||
*
|
*
|
||||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||||
* @param width the width of the image
|
* @param width the width of the image
|
||||||
@@ -154,7 +154,7 @@ public class FlatSVGUtils
|
|||||||
* Creates a buffered image and renders the given SVG into it.
|
* Creates a buffered image and renders the given SVG into it.
|
||||||
* <p>
|
* <p>
|
||||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||||
* Otherwise, use {@link #svg2image(URL, float)}.
|
* Otherwise use {@link #svg2image(URL, float)}.
|
||||||
*
|
*
|
||||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||||
* @param scaleFactor the amount by which the SVG size is scaled
|
* @param scaleFactor the amount by which the SVG size is scaled
|
||||||
|
|||||||
@@ -557,7 +557,7 @@ public class FlatUIDefaultsInspector
|
|||||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
panel = new JPanel();
|
panel = new JPanel();
|
||||||
filterPanel = new JPanel();
|
filterPanel = new JPanel();
|
||||||
filterLabel = new JLabel();
|
flterLabel = new JLabel();
|
||||||
filterField = new FlatTextField();
|
filterField = new FlatTextField();
|
||||||
valueTypeLabel = new JLabel();
|
valueTypeLabel = new JLabel();
|
||||||
valueTypeField = new JComboBox<>();
|
valueTypeField = new JComboBox<>();
|
||||||
@@ -580,11 +580,11 @@ public class FlatUIDefaultsInspector
|
|||||||
((GridBagLayout)filterPanel.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 0.0, 1.0E-4};
|
((GridBagLayout)filterPanel.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 0.0, 1.0E-4};
|
||||||
((GridBagLayout)filterPanel.getLayout()).rowWeights = new double[] {0.0, 1.0E-4};
|
((GridBagLayout)filterPanel.getLayout()).rowWeights = new double[] {0.0, 1.0E-4};
|
||||||
|
|
||||||
//---- filterLabel ----
|
//---- flterLabel ----
|
||||||
filterLabel.setText("Filter:");
|
flterLabel.setText("Filter:");
|
||||||
filterLabel.setLabelFor(filterField);
|
flterLabel.setLabelFor(filterField);
|
||||||
filterLabel.setDisplayedMnemonic('F');
|
flterLabel.setDisplayedMnemonic('F');
|
||||||
filterPanel.add(filterLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
|
filterPanel.add(flterLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
|
||||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||||
new Insets(0, 0, 0, 10), 0, 0));
|
new Insets(0, 0, 0, 10), 0, 0));
|
||||||
|
|
||||||
@@ -668,7 +668,7 @@ public class FlatUIDefaultsInspector
|
|||||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
private JPanel panel;
|
private JPanel panel;
|
||||||
private JPanel filterPanel;
|
private JPanel filterPanel;
|
||||||
private JLabel filterLabel;
|
private JLabel flterLabel;
|
||||||
private FlatTextField filterField;
|
private FlatTextField filterField;
|
||||||
private JLabel valueTypeLabel;
|
private JLabel valueTypeLabel;
|
||||||
private JComboBox<String> valueTypeField;
|
private JComboBox<String> valueTypeField;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ new FormModel {
|
|||||||
} ) {
|
} ) {
|
||||||
name: "filterPanel"
|
name: "filterPanel"
|
||||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
name: "filterLabel"
|
name: "flterLabel"
|
||||||
"text": "Filter:"
|
"text": "Filter:"
|
||||||
"labelFor": new FormReference( "filterField" )
|
"labelFor": new FormReference( "filterField" )
|
||||||
"displayedMnemonic": 70
|
"displayedMnemonic": 70
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ public class FlatButton
|
|||||||
public enum ButtonType { none, square, roundRect, tab, help, toolBarButton, borderless }
|
public enum ButtonType { none, square, roundRect, tab, help, toolBarButton, borderless }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns type of button.
|
* Returns type of a button.
|
||||||
*/
|
*/
|
||||||
public ButtonType getButtonType() {
|
public ButtonType getButtonType() {
|
||||||
return getClientPropertyEnumString( BUTTON_TYPE, ButtonType.class, null, ButtonType.none );
|
return getClientPropertyEnumString( BUTTON_TYPE, ButtonType.class, null, ButtonType.none );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies type of button.
|
* Specifies type of a button.
|
||||||
*/
|
*/
|
||||||
public void setButtonType( ButtonType buttonType ) {
|
public void setButtonType( ButtonType buttonType ) {
|
||||||
if( buttonType == ButtonType.none )
|
if( buttonType == ButtonType.none )
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class FlatFormattedTextField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
@@ -135,7 +135,7 @@ public class FlatFormattedTextField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class FlatPasswordField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
@@ -135,7 +135,7 @@ public class FlatPasswordField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -502,29 +502,6 @@ public class FlatTabbedPane
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: enum names must be equal to allowed strings
|
|
||||||
/** @since 3.3 */ public enum TabRotation { none, auto, left, right }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns how the tabs should be rotated.
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public TabRotation getTabRotation() {
|
|
||||||
return getClientPropertyEnumString( TABBED_PANE_TAB_ROTATION, TabRotation.class,
|
|
||||||
"TabbedPane.tabRotation", TabRotation.none );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies how the tabs should be rotated.
|
|
||||||
*
|
|
||||||
* @since 3.3
|
|
||||||
*/
|
|
||||||
public void setTabRotation( TabRotation tabRotation ) {
|
|
||||||
putClientPropertyEnumString( TABBED_PANE_TAB_ROTATION, tabRotation );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the tab icon placement (relative to tab title).
|
* Returns the tab icon placement (relative to tab title).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class FlatTextField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
@@ -134,7 +134,7 @@ public class FlatTextField
|
|||||||
* 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 #setOutline(Object)}).
|
* (see {@link #setOutline(Object)}.
|
||||||
*
|
*
|
||||||
* @since 2
|
* @since 2
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ public class FlatToggleButton
|
|||||||
implements FlatComponentExtension, FlatStyleableComponent
|
implements FlatComponentExtension, FlatStyleableComponent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns type of button.
|
* Returns type of a button.
|
||||||
*/
|
*/
|
||||||
public ButtonType getButtonType() {
|
public ButtonType getButtonType() {
|
||||||
return getClientPropertyEnumString( BUTTON_TYPE, ButtonType.class, null, ButtonType.none );
|
return getClientPropertyEnumString( BUTTON_TYPE, ButtonType.class, null, ButtonType.none );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies type of button.
|
* Specifies type of a button.
|
||||||
*/
|
*/
|
||||||
public void setButtonType( ButtonType buttonType ) {
|
public void setButtonType( ButtonType buttonType ) {
|
||||||
if( buttonType == ButtonType.none )
|
if( buttonType == ButtonType.none )
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import com.formdev.flatlaf.FlatLaf;
|
|||||||
* <p>
|
* <p>
|
||||||
* The initial state is {@link State#INDETERMINATE}.
|
* The initial state is {@link State#INDETERMINATE}.
|
||||||
* <p>
|
* <p>
|
||||||
* By default, the third state is allowed and clicking on the checkbox cycles through all
|
* By default the third state is allowed and clicking on the checkbox cycles thru all
|
||||||
* three states. If you want that the user can cycle only through two states, disallow
|
* three states. If you want that the user can cycle only thru two states, disallow
|
||||||
* intermediate state using {@link #setAllowIndeterminate(boolean)}. Then you can still
|
* intermediate state using {@link #setAllowIndeterminate(boolean)}. Then you can still
|
||||||
* set the indeterminate state via API if necessary, but the user can not.
|
* set the indeterminate state via API if necessary, but the user can not.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.extras.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 opened in module-info.java.
|
* Otherwise the compiler outputs a warning because this package is opend 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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -175,9 +175,6 @@ Spinner.buttonPressedArrowColor = Spinner.buttonArrowColor
|
|||||||
|
|
||||||
#---- SplitPaneDivider ----
|
#---- SplitPaneDivider ----
|
||||||
|
|
||||||
SplitPaneDivider.draggingColor = SplitPane.background
|
|
||||||
SplitPaneDivider.hoverColor = SplitPane.background
|
|
||||||
SplitPaneDivider.pressedColor = SplitPane.background
|
|
||||||
SplitPaneDivider.oneTouchHoverArrowColor = SplitPaneDivider.oneTouchArrowColor
|
SplitPaneDivider.oneTouchHoverArrowColor = SplitPaneDivider.oneTouchArrowColor
|
||||||
SplitPaneDivider.oneTouchPressedArrowColor = SplitPaneDivider.oneTouchArrowColor
|
SplitPaneDivider.oneTouchPressedArrowColor = SplitPaneDivider.oneTouchArrowColor
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,6 @@ build script:
|
|||||||
artifactId: flatlaf-fonts-inter
|
artifactId: flatlaf-fonts-inter
|
||||||
version: (see button below)
|
version: (see button below)
|
||||||
|
|
||||||
Otherwise, download `flatlaf-fonts-inter-<version>.jar` here:
|
Otherwise download `flatlaf-fonts-inter-<version>.jar` here:
|
||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-fonts-inter)
|
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf-fonts-inter)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
// For maven compatibility, <font-version> should be in format <major>.<minor>[.<micro>].
|
// For maven compatibility, <font-version> should be in format <major>.<minor>[.<micro>].
|
||||||
// <build-number> is optional and should be incremented only if a new release is
|
// <build-number> is optional and should be incremented only if a new release is
|
||||||
// necessary, but the <font-version> has not changed.
|
// necessary, but the <font-version> has not changed.
|
||||||
version = "4.0"
|
version = "3.19"
|
||||||
|
|
||||||
if( !rootProject.hasProperty( "release" ) )
|
if( !rootProject.hasProperty( "release" ) )
|
||||||
version = version.toString() + "-SNAPSHOT"
|
version = version.toString() + "-SNAPSHOT"
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class FlatInterFont
|
|||||||
* new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
|
* new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*/
|
*/
|
||||||
public static final String FAMILY_SEMIBOLD = "Inter SemiBold";
|
public static final String FAMILY_SEMIBOLD = "Inter Semi Bold";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use for {@link #installStyle(String)} to install single font style.
|
* Use for {@link #installStyle(String)} to install single font style.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user