mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c00d99b85f | ||
|
|
0bf87b753d | ||
|
|
53f2730064 | ||
|
|
d487c3b005 | ||
|
|
fef6ae7ff7 | ||
|
|
f6b42754de | ||
|
|
2ae9bb381d | ||
|
|
53bde84710 | ||
|
|
d006ac27ff | ||
|
|
c478d28b71 | ||
|
|
99f7b9ad84 | ||
|
|
ab58101ce3 | ||
|
|
d8f3682dc0 | ||
|
|
1fec7ba553 | ||
|
|
418f55f34e | ||
|
|
05d795b2ae | ||
|
|
a365b750d9 | ||
|
|
0aecfb565f | ||
|
|
0cf4edd9e5 | ||
|
|
dd7b7c6aef | ||
|
|
0bd677c46b | ||
|
|
1a131d5206 | ||
|
|
016e515ae2 | ||
|
|
456ceb3c58 | ||
|
|
2169be1b45 | ||
|
|
49eb0b0201 | ||
|
|
2e222bcdea | ||
|
|
c7fa475128 | ||
|
|
4174b065f3 | ||
|
|
df6256d989 | ||
|
|
c27db56321 | ||
|
|
97bed8554a | ||
|
|
751c0e16e9 | ||
|
|
936de60700 | ||
|
|
f6b64d48ec | ||
|
|
b043da7d4c | ||
|
|
7e47cc2443 | ||
|
|
b8b45f9442 | ||
|
|
66337f9af6 | ||
|
|
54646706a0 | ||
|
|
e8ee037d09 | ||
|
|
6d705e568a | ||
|
|
e768791eba | ||
|
|
2aff7c97f9 | ||
|
|
ca6fc7773e | ||
|
|
a1395a5490 | ||
|
|
61dd4d71d6 | ||
|
|
6beda53238 | ||
|
|
941441d7e1 | ||
|
|
d10ea41b47 | ||
|
|
9458870f70 | ||
|
|
095794bbd1 | ||
|
|
c7fc0aa936 | ||
|
|
a8d98ced61 | ||
|
|
831b3d851a | ||
|
|
8c891c7016 | ||
|
|
5c4706cbc9 | ||
|
|
db66a6c4f0 | ||
|
|
0517e4fc02 | ||
|
|
dd7fa4a87d | ||
|
|
e5956900ea | ||
|
|
3755593c14 | ||
|
|
8ddd3b6d68 | ||
|
|
840083940d | ||
|
|
0cdfd29ecf | ||
|
|
bb32c727b6 | ||
|
|
f978c04750 | ||
|
|
b6a504e121 | ||
|
|
5fae367fab | ||
|
|
6e807f44b2 | ||
|
|
53ebed7f89 | ||
|
|
1c10c41808 | ||
|
|
01170b669b | ||
|
|
b56215e5e3 | ||
|
|
221e801561 | ||
|
|
90edbe23d7 | ||
|
|
5b16a814c8 | ||
|
|
ef01721464 |
62
.github/workflows/ci.yml
vendored
62
.github/workflows/ci.yml
vendored
@@ -19,40 +19,26 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# test against
|
||||
# - Java 1.8 (minimum requirement)
|
||||
# - Java 9 (first version with JPMS)
|
||||
# - Java 8 (minimum requirement)
|
||||
# - Java LTS versions (11, 17, ...)
|
||||
# - lastest Java version(s)
|
||||
java:
|
||||
- 1.8
|
||||
- 9
|
||||
- 8
|
||||
- 11 # LTS
|
||||
- 14
|
||||
- 15
|
||||
- 17 # LTS
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
if: matrix.java == '1.8'
|
||||
if: matrix.java == '8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
distribution: adopt # Java 8 and 11 are pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
@@ -80,22 +66,11 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
distribution: adopt # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Publish snapshot to oss.sonatype.org
|
||||
run: ./gradlew publish :flatlaf-theme-editor:build -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||
@@ -127,22 +102,11 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
distribution: adopt # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Release a new stable version to Maven Central
|
||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -Drelease=true
|
||||
|
||||
29
.github/workflows/natives.yml
vendored
29
.github/workflows/natives.yml
vendored
@@ -11,12 +11,14 @@ on:
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
@@ -27,28 +29,17 @@ jobs:
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Setup Java 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
- name: Cache Gradle cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
!~/.gradle/caches/modules-2/modules-2.lock
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
java-version: 11
|
||||
distribution: adopt
|
||||
cache: gradle
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew :flatlaf-natives-windows:build
|
||||
# --no-daemon is necessary on Windows otherwise caching Gradle would fail with:
|
||||
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||
run: ./gradlew :flatlaf-natives-windows:build --no-daemon
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
|
||||
86
CHANGELOG.md
86
CHANGELOG.md
@@ -1,6 +1,92 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 2.1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Menus: Improved usability of submenus. (PR #490; issue #247)
|
||||
- Menus: Scroll large menus using mouse wheel or up/down arrows. (issue #225)
|
||||
- Linux: Support using custom window decorations. Enable with
|
||||
`JFrame.setDefaultLookAndFeelDecorated(true)` and
|
||||
`JDialog.setDefaultLookAndFeelDecorated(true)` before creating a window.
|
||||
(issue #482)
|
||||
- ScrollBar: Added UI value `ScrollBar.minimumButtonSize` to specify minimum
|
||||
scroll arrow button size (if shown). (issue #493)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- PasswordField: Fixed reveal button appearance in IntelliJ themes. (issue #494)
|
||||
- ScrollBar: Center and scale arrows in scroll up/down buttons (if shown).
|
||||
(issue #493)
|
||||
- TextArea, TextPane and EditorPane: No longer select all text when component is
|
||||
focused for the first time. (issue #498; regression in FlatLaf 2.0)
|
||||
- TabbedPane: Disable all items in "Show Hidden Tabs" popup menu if tabbed pane
|
||||
is disabled.
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Method `FlatUIUtils.paintArrow()` (and class `FlatArrowButton`) now paints
|
||||
arrows one pixel smaller than before. To fix this, increase parameter
|
||||
`arrowSize` by one.
|
||||
|
||||
|
||||
## 2.0.2
|
||||
|
||||
- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on
|
||||
HiDPI screens when dragging window partly offscreen and back into screen
|
||||
bounds. (issue #477)
|
||||
- Repaint component when setting client property `JComponent.outline` (issue
|
||||
#480).
|
||||
- macOS: Fixed NPE when using some icons in main menu items. (issue #483)
|
||||
|
||||
|
||||
## 2.0.1
|
||||
|
||||
- Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471;
|
||||
regression in FlatLaf 2.0)
|
||||
- ToolTip: Fixed wrong tooltip location if component overrides
|
||||
`JComponent.getToolTipLocation()` and wants place tooltip under mouse
|
||||
location. (issue #468)
|
||||
- Extras: Added copy constructor to `FlatSVGIcon`. (issue #465)
|
||||
- Moved `module-info.class` from `META-INF\versions\9\` to root folder of JARs.
|
||||
(issue #466)
|
||||
|
||||
|
||||
## 2.0
|
||||
|
||||
- Added system property `flatlaf.nativeLibraryPath` to load native libraries
|
||||
from a directory. (PR #453)
|
||||
- Fixed "endless recursion in font" exception in
|
||||
`FlatLaf$ActiveFont.createValue()` if `UIManager.getFont()` is invoked from
|
||||
multiple threads. (issue #456)
|
||||
- PasswordField: Preserve reveal button state when switching theme. (PR #442;
|
||||
issue #173)
|
||||
- PasswordField: Reveal button did not show password if
|
||||
`JPasswordField.setEchoChar()` was invoked from application. (PR #442; issue
|
||||
#173)
|
||||
- Slider: Fixed/improved focused indicator color when changing accent color. (PR
|
||||
#375)
|
||||
- TextField:
|
||||
- Improved hover/pressed/selected colors of leading/trailing buttons (e.g.
|
||||
"reveal" button in password field). (issue #452)
|
||||
- Clear button no longer paints over round border. (issue #451)
|
||||
- Extras: Fixed concurrent loading of SVG icons on multiple threads. (issue
|
||||
#459)
|
||||
- Use FlatLaf native window decorations by default when running in
|
||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki)
|
||||
(instead of using JetBrains custom decorations). System variable
|
||||
`flatlaf.useJetBrainsCustomDecorations` is now `false` by default (was `true`
|
||||
in FlatLaf 1.x). (issue #454)
|
||||
- Native window decorations:
|
||||
- Fixed blurry iconify/maximize/close button hover rectangles at 125%, 150% or
|
||||
175% scaling. (issue #431)
|
||||
- Updated maximize and restore icons for Windows 11 style. (requires Java
|
||||
8u321, 11.0.14, 17.0.2 or 18+)
|
||||
- Updated hover and pressed colors of iconify/maximize/close buttons for
|
||||
Windows 11 style.
|
||||
|
||||
|
||||
## 2.0-rc1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
28
README.md
28
README.md
@@ -11,9 +11,9 @@ scales on **HiDPI** displays and runs on Java 8 or newer.
|
||||
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

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

|
||||
|
||||
|
||||
Buzz
|
||||
----
|
||||
|
||||
@@ -114,6 +126,11 @@ Buzz
|
||||
Applications using FlatLaf
|
||||
--------------------------
|
||||
|
||||
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||
visual query system for relational databases
|
||||
-  [MooInfo](https://github.com/rememberber/MooInfo) -
|
||||
visual implementation of OSHI, to view information about the system and
|
||||
hardware
|
||||
-  [Jailer](https://github.com/Wisser/Jailer) 11.2 -
|
||||
database subsetting and relational data browsing tool
|
||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
||||
@@ -149,9 +166,10 @@ Applications using FlatLaf
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||
checks your website
|
||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
||||
game
|
||||
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5+ - a sci-fi tabletop
|
||||
BattleTech simulator suite handling battles, unit building, and campaigns
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||
0.13.b024 - GUI builder for
|
||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "2.0-rc1"
|
||||
val developmentVersion = "2.0-SNAPSHOT"
|
||||
val releaseVersion = "2.1"
|
||||
val developmentVersion = "2.2-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
add( "java9Compile", sourceSets.main.get().output )
|
||||
add( "java9Implementation", sourceSets.main.get().output )
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -63,10 +63,8 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
jar {
|
||||
manifest.attributes( "Multi-Release" to "true" )
|
||||
|
||||
into( "META-INF/versions/9" ) {
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Signature file v4.1
|
||||
#Version 1.6
|
||||
#Version 2.0
|
||||
|
||||
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
|
||||
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
|
||||
@@ -31,6 +31,8 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "al
|
||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
||||
fld public final static java.lang.String SQUARE_SIZE = "JButton.squareSize"
|
||||
fld public final static java.lang.String STYLE = "FlatLaf.style"
|
||||
fld public final static java.lang.String STYLE_CLASS = "FlatLaf.styleClass"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_CENTER = "center"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_FILL = "fill"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_LEADING = "leading"
|
||||
@@ -59,6 +61,9 @@ fld public final static java.lang.String TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT = "JT
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_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_TYPE = "JTabbedPane.tabType"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_CARD = "card"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE = "JTabbedPane.tabWidthMode"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_COMPACT = "compact"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_EQUAL = "equal"
|
||||
@@ -67,12 +72,20 @@ fld public final static java.lang.String TABBED_PANE_TRAILING_COMPONENT = "JTabb
|
||||
fld public final static java.lang.String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground"
|
||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_COLOR = "JToggleButton.tab.underlineColor"
|
||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_HEIGHT = "JToggleButton.tab.underlineHeight"
|
||||
fld public final static java.lang.String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback"
|
||||
fld public final static java.lang.String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent"
|
||||
fld public final static java.lang.String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon"
|
||||
fld public final static java.lang.String TEXT_FIELD_PADDING = "JTextField.padding"
|
||||
fld public final static java.lang.String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton"
|
||||
fld public final static java.lang.String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent"
|
||||
fld public final static java.lang.String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon"
|
||||
fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground"
|
||||
fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon"
|
||||
fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection"
|
||||
fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection"
|
||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"
|
||||
meth public static <%0 extends java.lang.Object> {%%0} clientProperty(javax.swing.JComponent,java.lang.String,{%%0},java.lang.Class<{%%0}>)
|
||||
meth public static boolean clientPropertyBoolean(javax.swing.JComponent,java.lang.String,boolean)
|
||||
meth public static boolean clientPropertyEquals(javax.swing.JComponent,java.lang.String,java.lang.Object)
|
||||
meth public static int clientPropertyInt(javax.swing.JComponent,java.lang.String,int)
|
||||
@@ -165,6 +178,7 @@ meth public boolean isSupportedLookAndFeel()
|
||||
meth public final boolean equals(java.lang.Object)
|
||||
meth public final int hashCode()
|
||||
meth public java.lang.String getID()
|
||||
meth public java.util.Map<java.lang.String,java.lang.String> getExtraDefaults()
|
||||
meth public javax.swing.Icon getDisabledIcon(javax.swing.JComponent,javax.swing.Icon)
|
||||
meth public javax.swing.UIDefaults getDefaults()
|
||||
meth public static boolean install(javax.swing.LookAndFeel)
|
||||
@@ -174,6 +188,8 @@ meth public static boolean isShowMnemonics()
|
||||
meth public static boolean isUseNativeWindowDecorations()
|
||||
meth public static boolean setup(javax.swing.LookAndFeel)
|
||||
meth public static boolean supportsNativeWindowDecorations()
|
||||
meth public static java.lang.Object parseDefaultsValue(java.lang.String,java.lang.String,java.lang.Class<?>)
|
||||
meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults()
|
||||
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
|
||||
meth public static void hideMnemonics()
|
||||
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
||||
@@ -181,22 +197,26 @@ meth public static void installLafInfo(java.lang.String,java.lang.Class<? extend
|
||||
meth public static void registerCustomDefaultsSource(java.io.File)
|
||||
meth public static void registerCustomDefaultsSource(java.lang.String)
|
||||
meth public static void registerCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||
meth public static void registerCustomDefaultsSource(java.net.URL)
|
||||
meth public static void repaintAllFramesAndDialogs()
|
||||
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
||||
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
||||
meth public static void setGlobalExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||
meth public static void setUseNativeWindowDecorations(boolean)
|
||||
meth public static void showMnemonics(java.awt.Component)
|
||||
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
||||
meth public static void unregisterCustomDefaultsSource(java.lang.String)
|
||||
meth public static void unregisterCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||
meth public static void unregisterCustomDefaultsSource(java.net.URL)
|
||||
meth public static void updateUI()
|
||||
meth public static void updateUILater()
|
||||
meth public void initialize()
|
||||
meth public void registerUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||
meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||
meth public void uninitialize()
|
||||
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||
supr javax.swing.plaf.basic.BasicLookAndFeel
|
||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,mnemonicHandler,oldPopupFactory,postInitialization,uiDefaultsGetters,updateUIPending
|
||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,uiDefaultsGetters,updateUIPending
|
||||
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
||||
@@ -231,6 +251,7 @@ hfds baseTheme,dark,name,properties
|
||||
CLSS public abstract interface com.formdev.flatlaf.FlatSystemProperties
|
||||
fld public final static java.lang.String ANIMATION = "flatlaf.animation"
|
||||
fld public final static java.lang.String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded"
|
||||
fld public final static java.lang.String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath"
|
||||
fld public final static java.lang.String UI_SCALE = "flatlaf.uiScale"
|
||||
fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown"
|
||||
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
||||
@@ -330,7 +351,15 @@ innr public static HSLIncreaseDecrease
|
||||
innr public static Mix
|
||||
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
||||
meth public static float clamp(float)
|
||||
meth public static float luma(java.awt.Color)
|
||||
meth public static java.awt.Color darken(java.awt.Color,float)
|
||||
meth public static java.awt.Color desaturate(java.awt.Color,float)
|
||||
meth public static java.awt.Color lighten(java.awt.Color,float)
|
||||
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
||||
meth public static java.awt.Color saturate(java.awt.Color,float)
|
||||
meth public static java.awt.Color shade(java.awt.Color,float)
|
||||
meth public static java.awt.Color spin(java.awt.Color,float)
|
||||
meth public static java.awt.Color tint(java.awt.Color,float)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.util.ColorFunctions$ColorFunction
|
||||
@@ -566,6 +595,7 @@ meth public static java.util.List<java.awt.Image> getResolutionVariants(java.awt
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
||||
cons public init(java.io.File,boolean)
|
||||
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
||||
meth public boolean isLoaded()
|
||||
supr java.lang.Object
|
||||
@@ -589,18 +619,52 @@ meth public void paintIcon(java.awt.Component,java.awt.Graphics,int,int)
|
||||
supr java.lang.Object
|
||||
hfds iconHeight,iconWidth,imageIcon,lastImage,lastSystemScaleFactor,lastUserScaleFactor
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SoftCache<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||
cons public init()
|
||||
cons public init(int)
|
||||
intf java.util.Map<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>
|
||||
meth public boolean containsKey(java.lang.Object)
|
||||
meth public boolean containsValue(java.lang.Object)
|
||||
meth public boolean isEmpty()
|
||||
meth public int size()
|
||||
meth public java.util.Collection<{com.formdev.flatlaf.util.SoftCache%1}> values()
|
||||
meth public java.util.Set<java.util.Map$Entry<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>> entrySet()
|
||||
meth public java.util.Set<{com.formdev.flatlaf.util.SoftCache%0}> keySet()
|
||||
meth public void clear()
|
||||
meth public void forEach(java.util.function.BiConsumer<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public void putAll(java.util.Map<? extends {com.formdev.flatlaf.util.SoftCache%0},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public void replaceAll(java.util.function.BiFunction<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} get(java.lang.Object)
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} put({com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1})
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} remove(java.lang.Object)
|
||||
supr java.lang.Object
|
||||
hfds map,queue
|
||||
hcls CacheReference
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.StringUtils
|
||||
cons public init()
|
||||
meth public static boolean isEmpty(java.lang.String)
|
||||
meth public static boolean isTrimmedEmpty(java.lang.String)
|
||||
meth public static java.lang.String removeLeading(java.lang.String,java.lang.String)
|
||||
meth public static java.lang.String removeTrailing(java.lang.String,java.lang.String)
|
||||
meth public static java.lang.String substringTrimmed(java.lang.String,int)
|
||||
meth public static java.lang.String substringTrimmed(java.lang.String,int,int)
|
||||
meth public static java.util.List<java.lang.String> split(java.lang.String,char)
|
||||
meth public static java.util.List<java.lang.String> split(java.lang.String,char,boolean,boolean)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SwingUtils
|
||||
cons public init()
|
||||
meth public static <%0 extends java.awt.Component> {%%0} getComponentByName(java.awt.Container,java.lang.String)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SystemInfo
|
||||
cons public init()
|
||||
fld public final static boolean isAARCH64
|
||||
fld public final static boolean isJava_11_orLater
|
||||
fld public final static boolean isJava_15_orLater
|
||||
fld public final static boolean isJava_17_orLater
|
||||
fld public final static boolean isJava_18_orLater
|
||||
fld public final static boolean isJava_9_orLater
|
||||
fld public final static boolean isJetBrainsJVM
|
||||
fld public final static boolean isJetBrainsJVM_11_orLater
|
||||
@@ -615,6 +679,8 @@ fld public final static boolean isWebswing
|
||||
fld public final static boolean isWinPE
|
||||
fld public final static boolean isWindows
|
||||
fld public final static boolean isWindows_10_orLater
|
||||
fld public final static boolean isWindows_11_orLater
|
||||
fld public final static boolean isX86
|
||||
fld public final static boolean isX86_64
|
||||
fld public final static long javaVersion
|
||||
fld public final static long osVersion
|
||||
@@ -627,6 +693,7 @@ cons public init()
|
||||
meth public static boolean isSystemScalingEnabled()
|
||||
meth public static double getSystemScaleFactor(java.awt.Graphics2D)
|
||||
meth public static double getSystemScaleFactor(java.awt.GraphicsConfiguration)
|
||||
meth public static float computeFontScaleFactor(java.awt.Font)
|
||||
meth public static float getUserScaleFactor()
|
||||
meth public static float scale(float)
|
||||
meth public static float unscale(float)
|
||||
@@ -933,6 +1000,34 @@ CLSS public abstract interface !annotation java.lang.annotation.Target
|
||||
intf java.lang.annotation.Annotation
|
||||
meth public abstract java.lang.annotation.ElementType[] value()
|
||||
|
||||
CLSS public abstract interface java.util.Map<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||
innr public abstract interface static Entry
|
||||
meth public abstract boolean containsKey(java.lang.Object)
|
||||
meth public abstract boolean containsValue(java.lang.Object)
|
||||
meth public abstract boolean equals(java.lang.Object)
|
||||
meth public abstract boolean isEmpty()
|
||||
meth public abstract int hashCode()
|
||||
meth public abstract int size()
|
||||
meth public abstract java.util.Collection<{java.util.Map%1}> values()
|
||||
meth public abstract java.util.Set<java.util.Map$Entry<{java.util.Map%0},{java.util.Map%1}>> entrySet()
|
||||
meth public abstract java.util.Set<{java.util.Map%0}> keySet()
|
||||
meth public abstract void clear()
|
||||
meth public abstract void putAll(java.util.Map<? extends {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||
meth public abstract {java.util.Map%1} get(java.lang.Object)
|
||||
meth public abstract {java.util.Map%1} put({java.util.Map%0},{java.util.Map%1})
|
||||
meth public abstract {java.util.Map%1} remove(java.lang.Object)
|
||||
meth public boolean remove(java.lang.Object,java.lang.Object)
|
||||
meth public boolean replace({java.util.Map%0},{java.util.Map%1},{java.util.Map%1})
|
||||
meth public void forEach(java.util.function.BiConsumer<? super {java.util.Map%0},? super {java.util.Map%1}>)
|
||||
meth public void replaceAll(java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} compute({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} computeIfAbsent({java.util.Map%0},java.util.function.Function<? super {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} computeIfPresent({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} getOrDefault(java.lang.Object,{java.util.Map%1})
|
||||
meth public {java.util.Map%1} merge({java.util.Map%0},{java.util.Map%1},java.util.function.BiFunction<? super {java.util.Map%1},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} putIfAbsent({java.util.Map%0},{java.util.Map%1})
|
||||
meth public {java.util.Map%1} replace({java.util.Map%0},{java.util.Map%1})
|
||||
|
||||
CLSS public abstract interface javax.swing.Icon
|
||||
meth public abstract int getIconHeight()
|
||||
meth public abstract int getIconWidth()
|
||||
|
||||
@@ -874,7 +874,26 @@ public interface FlatClientProperties
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #OUTLINE}.
|
||||
* (see {@link #OUTLINE}).
|
||||
* <p>
|
||||
* The component is prepared in the following way:
|
||||
* <ul>
|
||||
* <li>Component client property {@link #STYLE_CLASS} is set to {@code inTextField}.
|
||||
* <li>If component is a button or toggle button, client property {@link #BUTTON_TYPE}
|
||||
* is set to {@link #BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||
* and button cursor is set to default cursor (if not set).
|
||||
* <li>If component is a toolbar, client property {@link #STYLE_CLASS}
|
||||
* is set to {@code inTextField} on all toolbar children
|
||||
* and toolbar cursor is set to default cursor (if not set).
|
||||
* </ul>
|
||||
* Because text fields use the text cursor by default and the cursor is inherited by child components,
|
||||
* it may be necessary to explicitly set component cursor if you e.g. need the default arrow cursor.
|
||||
* E.g. {@code comp.setCursor( Cursor.getDefaultCursor() )}.
|
||||
* <p>
|
||||
* Styling is used to modify insets/margins and appearance of buttons and toolbars
|
||||
* so that they fit nicely into the text field and do not increase text field height.
|
||||
* See styles {@code [style]Button.inTextField} and {@code [style]ToolBar.inTextField}
|
||||
* in {@code Flat[Light|Dark]Laf.properties}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
@@ -886,15 +905,7 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #OUTLINE}.
|
||||
* See {@link #TEXT_FIELD_LEADING_COMPONENT} for details.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
|
||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
||||
* Allows loading of additional .properties files from addon JARs.
|
||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||
* <p>
|
||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
||||
* If you extend this class in an addon JAR, you also have to add a text file named
|
||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||
* to the addon JAR. The file must contain a single line with the class name.
|
||||
* <p>
|
||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
||||
|
||||
/**
|
||||
* Returns the priority used to sort addon loading.
|
||||
* The order is only important if you want overwrite UI defaults of other addons.
|
||||
* The order is only important if you want to overwrite UI defaults of other addons.
|
||||
* Lower numbers mean higher priority.
|
||||
* Returns 10000 by default.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
||||
/**
|
||||
* Default color palette for action icons and object icons.
|
||||
* <p>
|
||||
* The idea is to use only this well defined set of colors in SVG icons and
|
||||
* The idea is to use only this well-defined set of colors in SVG icons, and
|
||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
||||
* <p>
|
||||
* You may use these colors also in your application (outside of SVG icons), but do
|
||||
* not use the RGB values defined in this enum.<br>
|
||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -596,7 +596,7 @@ class FlatInputMaps
|
||||
//---- class LazyInputMapEx -----------------------------------------------
|
||||
|
||||
/**
|
||||
* Lazily creates a input map.
|
||||
* Lazily creates an input map.
|
||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||
*/
|
||||
private static class LazyInputMapEx
|
||||
|
||||
@@ -103,6 +103,7 @@ public abstract class FlatLaf
|
||||
|
||||
private PopupFactory oldPopupFactory;
|
||||
private MnemonicHandler mnemonicHandler;
|
||||
private SubMenuUsabilityHelper subMenuUsabilityHelper;
|
||||
|
||||
private Consumer<UIDefaults> postInitialization;
|
||||
private List<Function<Object, Object>> uiDefaultsGetters;
|
||||
@@ -166,18 +167,19 @@ public abstract class FlatLaf
|
||||
* Returns whether FlatLaf supports custom window decorations.
|
||||
* This depends on the operating system and on the used Java runtime.
|
||||
* <p>
|
||||
* This method returns {@code true} on Windows 10 (see exception below), {@code false} otherwise.
|
||||
* This method returns {@code true} on Windows 10/11 (see exception below)
|
||||
* and on Linux, {@code false} otherwise.
|
||||
* <p>
|
||||
* Returns also {@code false} on Windows 10 if:
|
||||
* Returns also {@code false} on Windows 10/11 if:
|
||||
* <ul>
|
||||
* <li>FlatLaf native window border support is available (requires Windows 10)</li>
|
||||
* <li>FlatLaf native window border support is available (requires Windows 10/11)</li>
|
||||
* <li>running in
|
||||
* <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 this cases, custom decorations are enabled by the root pane.
|
||||
* In these cases, custom decorations are enabled by the root pane.
|
||||
* Usage of {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} or
|
||||
* {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} is not necessary.
|
||||
*/
|
||||
@@ -190,7 +192,7 @@ public abstract class FlatLaf
|
||||
FlatNativeWindowBorder.isSupported() )
|
||||
return false;
|
||||
|
||||
return SystemInfo.isWindows_10_orLater;
|
||||
return SystemInfo.isWindows_10_orLater || SystemInfo.isLinux;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,6 +245,10 @@ public abstract class FlatLaf
|
||||
mnemonicHandler = new MnemonicHandler();
|
||||
mnemonicHandler.install();
|
||||
|
||||
// install submenu usability helper
|
||||
subMenuUsabilityHelper = new SubMenuUsabilityHelper();
|
||||
subMenuUsabilityHelper.install();
|
||||
|
||||
// listen to desktop property changes to update UI if system font or scaling changes
|
||||
if( SystemInfo.isWindows ) {
|
||||
// Windows 10 allows increasing font size independent of scaling:
|
||||
@@ -322,6 +328,12 @@ public abstract class FlatLaf
|
||||
mnemonicHandler = null;
|
||||
}
|
||||
|
||||
// uninstall submenu usability helper
|
||||
if( subMenuUsabilityHelper != null ) {
|
||||
subMenuUsabilityHelper.uninstall();
|
||||
subMenuUsabilityHelper = null;
|
||||
}
|
||||
|
||||
// restore default link color
|
||||
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
|
||||
postInitialization = null;
|
||||
@@ -605,7 +617,7 @@ public abstract class FlatLaf
|
||||
uiFont = ((ActiveFont)defaultFont).derive( baseFont, fontSize -> {
|
||||
return Math.round( fontSize * UIScale.computeFontScaleFactor( baseFont ) );
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
// increase font size if system property "flatlaf.uiScale" is set
|
||||
uiFont = UIScale.applyCustomScaleFactor( uiFont );
|
||||
@@ -760,7 +772,7 @@ public abstract class FlatLaf
|
||||
* Invoke this method before setting the look and feel.
|
||||
* <p>
|
||||
* If using Java modules, the package must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #registerCustomDefaultsSource(URL)}.
|
||||
* Otherwise, use {@link #registerCustomDefaultsSource(URL)}.
|
||||
*
|
||||
* @param packageName a package name (e.g. "com.myapp.resources")
|
||||
*/
|
||||
@@ -862,7 +874,7 @@ public abstract class FlatLaf
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
@@ -894,7 +906,7 @@ public abstract class FlatLaf
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
@@ -951,7 +963,7 @@ public abstract class FlatLaf
|
||||
// re-set current LaF
|
||||
UIManager.setLookAndFeel( lookAndFeel );
|
||||
|
||||
// must fire property change events ourself because old and new LaF are the same
|
||||
// must fire property change events ourselves because old and new LaF are the same
|
||||
PropertyChangeEvent e = new PropertyChangeEvent( UIManager.class, "lookAndFeel", lookAndFeel, lookAndFeel );
|
||||
for( PropertyChangeListener l : UIManager.getPropertyChangeListeners() )
|
||||
l.propertyChange( e );
|
||||
@@ -995,7 +1007,7 @@ public abstract class FlatLaf
|
||||
/**
|
||||
* Returns whether native window decorations are supported on current platform.
|
||||
* <p>
|
||||
* This requires Windows 10, but may be disabled if running in special environments
|
||||
* This requires Windows 10/11, but may be disabled if running in special environments
|
||||
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
|
||||
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
|
||||
* {@code false}, then this method also returns {@code false}.
|
||||
@@ -1223,6 +1235,9 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
private Object getValue( Object key ) {
|
||||
// use local variable for getters to avoid potential multi-threading issues
|
||||
List<Function<Object, Object>> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters;
|
||||
|
||||
if( uiDefaultsGetters == null )
|
||||
return null;
|
||||
|
||||
@@ -1276,8 +1291,9 @@ public abstract class FlatLaf
|
||||
this.scaleSize = scaleSize;
|
||||
}
|
||||
|
||||
// using synchronized to avoid exception if invoked at the same time on multiple threads
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
public synchronized Object createValue( UIDefaults table ) {
|
||||
if( inCreateValue )
|
||||
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public interface FlatSystemProperties
|
||||
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||
* which has the same syntax as this one.
|
||||
* <p>
|
||||
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
|
||||
* Since FlatLaf 1.1.2: Scale factors less than 100% are allowed.
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||
* UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -92,16 +92,16 @@ public interface FlatSystemProperties
|
||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||
* when creating {@code JFrame} or {@code JDialog}.
|
||||
* Requires that the application runs in a
|
||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
|
||||
* <a href="https://github.com/JetBrains/JetBrainsRuntime/wiki">JetBrains Runtime</a>
|
||||
* (based on OpenJDK).
|
||||
* <p>
|
||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||
* Then FlatLaf native window decorations are used.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> {@code true}
|
||||
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||
*/
|
||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||
|
||||
@@ -116,7 +116,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -139,6 +139,15 @@ public interface FlatSystemProperties
|
||||
*/
|
||||
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
||||
|
||||
/**
|
||||
* Specifies a directory in which the native FlatLaf library have been extracted.
|
||||
* The path can be absolute or relative to current application working directory.
|
||||
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
||||
|
||||
/**
|
||||
* Checks whether a system property is set and returns {@code true} if its value
|
||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||
|
||||
@@ -175,7 +175,7 @@ public class IntelliJTheme
|
||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
|
||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
// IDEA uses an SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
||||
if( helpButtonBackground == null )
|
||||
@@ -242,7 +242,19 @@ public class IntelliJTheme
|
||||
defaults.put( "Tree.rowHeight", 22 );
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
defaults.putAll( themeSpecificDefaults );
|
||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||
Object key = e.getKey();
|
||||
Object value = e.getValue();
|
||||
|
||||
// append styles to existing styles
|
||||
if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
|
||||
Object oldValue = defaults.get( key );
|
||||
if( oldValue != null )
|
||||
value = oldValue + "; " + value;
|
||||
}
|
||||
|
||||
defaults.put( key, value );
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
@@ -534,12 +546,12 @@ public class IntelliJTheme
|
||||
}
|
||||
|
||||
/** Rename UI default keys (key --> value). */
|
||||
private static Map<String, String> uiKeyMapping = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||
/** Copy UI default keys (value --> key). */
|
||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyCopying = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
|
||||
static {
|
||||
// ComboBox
|
||||
|
||||
@@ -170,7 +170,7 @@ class LinuxFontPolicy
|
||||
|
||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||
if( value instanceof Integer ) {
|
||||
int dpi = ((Integer)value).intValue() / 1024;
|
||||
int dpi = (Integer) value / 1024;
|
||||
if( dpi == -1 )
|
||||
dpi = 96;
|
||||
if( dpi < 50 )
|
||||
@@ -197,7 +197,7 @@ class LinuxFontPolicy
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default font for KDE for KDE configuration files.
|
||||
* Gets the default font for KDE from KDE configuration files.
|
||||
*
|
||||
* The Swing fonts are not updated when the user changes system font size
|
||||
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
||||
@@ -278,7 +278,7 @@ class LinuxFontPolicy
|
||||
// read config file
|
||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
||||
String line = null;
|
||||
String line;
|
||||
while( (line = reader.readLine()) != null )
|
||||
lines.add( line );
|
||||
} catch( IOException ex ) {
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.Point;
|
||||
import java.awt.PointerInfo;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* Improves usability of submenus by using a
|
||||
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class SubMenuUsabilityHelper
|
||||
implements ChangeListener
|
||||
{
|
||||
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||
|
||||
private SubMenuEventQueue subMenuEventQueue;
|
||||
private SafeTrianglePainter safeTrianglePainter;
|
||||
private boolean changePending;
|
||||
|
||||
// mouse location in screen coordinates
|
||||
private int mouseX;
|
||||
private int mouseY;
|
||||
|
||||
// target popup bounds in screen coordinates
|
||||
private int targetX;
|
||||
private int targetTopY;
|
||||
private int targetBottomY;
|
||||
|
||||
private Rectangle invokerBounds;
|
||||
|
||||
void install() {
|
||||
MenuSelectionManager.defaultManager().addChangeListener( this );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
MenuSelectionManager.defaultManager().removeChangeListener( this );
|
||||
uninstallEventQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
if( !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||
return;
|
||||
|
||||
// handle menu selection change later, but only once in case of temporary changes
|
||||
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||
// 1. old menu item is removed from menu selection
|
||||
// 2. new menu item is added to menu selection
|
||||
synchronized( this ) {
|
||||
if( changePending )
|
||||
return;
|
||||
changePending = true;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
synchronized( this ) {
|
||||
changePending = false;
|
||||
}
|
||||
menuSelectionChanged();
|
||||
} );
|
||||
}
|
||||
|
||||
private void menuSelectionChanged() {
|
||||
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
|
||||
/*debug
|
||||
System.out.println( "--- " + path.length );
|
||||
for( int i = 0; i < path.length; i++ )
|
||||
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||
debug*/
|
||||
|
||||
// find submenu in menu selection
|
||||
int subMenuIndex = findSubMenu( path );
|
||||
|
||||
// uninstall if there is no submenu in selection
|
||||
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current mouse location
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||
mouseX = mouseLocation.x;
|
||||
mouseY = mouseLocation.y;
|
||||
|
||||
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||
if( !popup.isShowing() ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// get invoker screen bounds
|
||||
Component invoker = popup.getInvoker();
|
||||
invokerBounds = (invoker != null)
|
||||
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||
: null;
|
||||
|
||||
// check whether mouse location is within invoker
|
||||
if( invokerBounds != null && !invokerBounds.contains( mouseX, mouseY ) ) {
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
// compute top/bottom target locations
|
||||
Point popupLocation = popup.getLocationOnScreen();
|
||||
Dimension popupSize = popup.getSize();
|
||||
targetX = (mouseX < popupLocation.x + (popupSize.width / 2))
|
||||
? popupLocation.x
|
||||
: popupLocation.x + popupSize.width;
|
||||
targetTopY = popupLocation.y;
|
||||
targetBottomY = popupLocation.y + popupSize.height;
|
||||
|
||||
// install own event queue to supress mouse events when mouse is moved within safe triangle
|
||||
if( subMenuEventQueue == null )
|
||||
subMenuEventQueue = new SubMenuEventQueue();
|
||||
|
||||
// create safe triangle painter
|
||||
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||
safeTrianglePainter = new SafeTrianglePainter( popup );
|
||||
}
|
||||
|
||||
private void uninstallEventQueue() {
|
||||
if( subMenuEventQueue != null ) {
|
||||
subMenuEventQueue.uninstall();
|
||||
subMenuEventQueue = null;
|
||||
}
|
||||
|
||||
if( safeTrianglePainter != null ) {
|
||||
safeTrianglePainter.uninstall();
|
||||
safeTrianglePainter = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int findSubMenu( MenuElement[] path ) {
|
||||
for( int i = path.length - 1; i >= 1; i-- ) {
|
||||
if( path[i] instanceof JPopupMenu &&
|
||||
path[i - 1] instanceof JMenu &&
|
||||
!((JMenu)path[i - 1]).isTopLevelMenu() )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Polygon createSafeTriangle() {
|
||||
return new Polygon(
|
||||
new int[] { mouseX, targetX, targetX },
|
||||
new int[] { mouseY, targetTopY, targetBottomY },
|
||||
3 );
|
||||
}
|
||||
|
||||
//---- class SubMenuEventQueue --------------------------------------------
|
||||
|
||||
private class SubMenuEventQueue
|
||||
extends EventQueue
|
||||
{
|
||||
private Timer mouseUpdateTimer;
|
||||
private Timer timeoutTimer;
|
||||
|
||||
private int newMouseX;
|
||||
private int newMouseY;
|
||||
private AWTEvent lastMouseEvent;
|
||||
|
||||
SubMenuEventQueue() {
|
||||
// timer used to slightly delay update of mouse location used for safe triangle
|
||||
mouseUpdateTimer = new Timer( 50, e -> {
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
} );
|
||||
mouseUpdateTimer.setRepeats( false );
|
||||
|
||||
// timer used to timeout safe triangle when mouse stops moving
|
||||
timeoutTimer = new Timer( 200, e -> {
|
||||
if( invokerBounds != null && !invokerBounds.contains( newMouseX, newMouseY ) ) {
|
||||
// post last mouse event, which selects menu item at mouse location
|
||||
if( lastMouseEvent != null ) {
|
||||
postEvent( lastMouseEvent );
|
||||
lastMouseEvent = null;
|
||||
}
|
||||
|
||||
uninstallEventQueue();
|
||||
return;
|
||||
}
|
||||
} );
|
||||
timeoutTimer.setRepeats( false );
|
||||
|
||||
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
mouseUpdateTimer.stop();
|
||||
mouseUpdateTimer = null;
|
||||
|
||||
timeoutTimer.stop();
|
||||
timeoutTimer = null;
|
||||
|
||||
lastMouseEvent = null;
|
||||
|
||||
super.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchEvent( AWTEvent e ) {
|
||||
int id = e.getID();
|
||||
|
||||
if( e instanceof MouseEvent &&
|
||||
(id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED) )
|
||||
{
|
||||
newMouseX = ((MouseEvent)e).getXOnScreen();
|
||||
newMouseY = ((MouseEvent)e).getYOnScreen();
|
||||
|
||||
if( safeTrianglePainter != null )
|
||||
safeTrianglePainter.repaint();
|
||||
|
||||
mouseUpdateTimer.stop();
|
||||
timeoutTimer.stop();
|
||||
|
||||
// check whether mouse moved within safe triangle
|
||||
if( createSafeTriangle().contains( newMouseX, newMouseY ) ) {
|
||||
// update mouse location delayed (this changes the safe triangle)
|
||||
mouseUpdateTimer.start();
|
||||
|
||||
timeoutTimer.start();
|
||||
|
||||
// remember last mouse event, which will be posted if the mouse stops moving
|
||||
lastMouseEvent = e;
|
||||
|
||||
// ignore mouse event
|
||||
return;
|
||||
}
|
||||
|
||||
// update mouse location immediately (this changes the safe triangle)
|
||||
mouseX = newMouseX;
|
||||
mouseY = newMouseY;
|
||||
}
|
||||
|
||||
super.dispatchEvent( e );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class SafeTrianglePainter ------------------------------------------
|
||||
|
||||
private class SafeTrianglePainter
|
||||
extends JComponent
|
||||
{
|
||||
SafeTrianglePainter( JPopupMenu popup ) {
|
||||
Window window = SwingUtilities.windowForComponent( popup.getInvoker() );
|
||||
if( window instanceof RootPaneContainer ) {
|
||||
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||
setSize( layeredPane.getSize() );
|
||||
layeredPane.add( this, new Integer( JLayeredPane.POPUP_LAYER + 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
Container parent = getParent();
|
||||
if( parent != null ) {
|
||||
parent.remove( this );
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent( Graphics g ) {
|
||||
Point locationOnScreen = getLocationOnScreen();
|
||||
g.translate( -locationOnScreen.x, -locationOnScreen.y );
|
||||
|
||||
g.setColor( Color.red );
|
||||
((Graphics2D)g).draw( createSafeTriangle() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,7 +350,7 @@ class UIDefaultsLoader
|
||||
enum ValueType { UNKNOWN, STRING, BOOLEAN, CHARACTER, INTEGER, INTEGERORFLOAT, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR, FONT,
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER, NULL, LAZY }
|
||||
|
||||
private static ValueType[] tempResultValueType = new ValueType[1];
|
||||
private static final ValueType[] tempResultValueType = new ValueType[1];
|
||||
private static Map<Class<?>, ValueType> javaValueTypes;
|
||||
private static Map<String, ValueType> knownValueTypes;
|
||||
|
||||
@@ -792,7 +792,7 @@ class UIDefaultsLoader
|
||||
* Syntax: if(condition,trueValue,falseValue)
|
||||
* <p>
|
||||
* This "if" function is only used if the "if" is passed as parameter to another
|
||||
* color function. Otherwise the general "if" function is used.
|
||||
* color function. Otherwise, the general "if" function is used.
|
||||
*/
|
||||
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||
if( params.size() != 3 )
|
||||
@@ -902,21 +902,32 @@ class UIDefaultsLoader
|
||||
* Syntax: fade(color,amount[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - amount: percentage 0-100%
|
||||
* - options: [derived]
|
||||
* - options: [derived] [lazy]
|
||||
*/
|
||||
private static Object parseColorFade( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||
String colorStr = params.get( 0 );
|
||||
int amount = parsePercentage( params.get( 1 ) );
|
||||
boolean derived = false;
|
||||
boolean lazy = false;
|
||||
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
derived = options.contains( "derived" );
|
||||
lazy = options.contains( "lazy" );
|
||||
}
|
||||
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.Fade( amount );
|
||||
|
||||
if( lazy ) {
|
||||
return (LazyValue) t -> {
|
||||
Object color = lazyUIManagerGet( colorStr );
|
||||
return (color instanceof Color)
|
||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
// parse base color, apply function and create derived color
|
||||
return parseFunctionBaseColor( colorStr, function, derived, resolver, reportError );
|
||||
}
|
||||
@@ -1198,7 +1209,7 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
Integer integer = parseInteger( value, true );
|
||||
if( integer.intValue() < min || integer.intValue() > max )
|
||||
if( integer < min || integer > max )
|
||||
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
||||
return integer;
|
||||
}
|
||||
@@ -1239,28 +1250,28 @@ class UIDefaultsLoader
|
||||
|
||||
private static ActiveValue parseScaledInteger( String value ) {
|
||||
int val = parseInteger( value, true );
|
||||
return (ActiveValue) t -> {
|
||||
return t -> {
|
||||
return UIScale.scale( val );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledFloat( String value ) {
|
||||
float val = parseFloat( value, true );
|
||||
return (ActiveValue) t -> {
|
||||
return t -> {
|
||||
return UIScale.scale( val );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledInsets( String value ) {
|
||||
Insets insets = parseInsets( value );
|
||||
return (ActiveValue) t -> {
|
||||
return t -> {
|
||||
return UIScale.scale( insets );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledDimension( String value ) {
|
||||
Dimension dimension = parseDimension( value );
|
||||
return (ActiveValue) t -> {
|
||||
return t -> {
|
||||
return UIScale.scale( dimension );
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||
|
||||
/**
|
||||
* Base class for animated icons that scales width and height, creates and initializes
|
||||
* Base class for animated icons that scale width and height, creates and initializes
|
||||
* a scaled graphics context for icon painting.
|
||||
* <p>
|
||||
* Subclasses do not need to scale icon painting.
|
||||
* <p>
|
||||
* This class does not store any state information (needed for animation) in its instance.
|
||||
* Instead a client property is set on the painted component.
|
||||
* Instead, a client property is set on the painted component.
|
||||
* This makes it possible to use a share icon instance for multiple components.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
|
||||
@@ -51,7 +51,7 @@ public class FlatAscendingSortIcon
|
||||
boolean chevron = this.chevron;
|
||||
Color sortIconColor = this.sortIconColor;
|
||||
|
||||
// Because this icons are always shared for all table headers,
|
||||
// Because this icon is always shared for all table headers,
|
||||
// get icon specific style from FlatTableHeaderUI.
|
||||
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
||||
if( tableHeader != null ) {
|
||||
|
||||
@@ -96,8 +96,8 @@ public class FlatHelpButtonIcon
|
||||
</svg>
|
||||
*/
|
||||
|
||||
boolean enabled = c.isEnabled();
|
||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||
boolean enabled = c == null || c.isEnabled();
|
||||
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||
|
||||
float xy = 0.5f;
|
||||
float wh = iconSize() - 1;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class FlatMenuArrowIcon
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
if( !c.getComponentOrientation().isLeftToRight() )
|
||||
if( c != null && !c.getComponentOrientation().isLeftToRight() )
|
||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||
|
||||
g.setColor( getArrowColor( c ) );
|
||||
@@ -82,7 +82,7 @@ public class FlatMenuArrowIcon
|
||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||
return selectionForeground;
|
||||
|
||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||
return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||
}
|
||||
|
||||
protected boolean isUnderlineSelection() {
|
||||
|
||||
@@ -76,7 +76,7 @@ public class FlatTreeCollapsedIcon
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this icons are always shared for all trees,
|
||||
* Because this icon is always shared for all trees,
|
||||
* get icon specific style from FlatTreeUI.
|
||||
*/
|
||||
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
@@ -65,8 +66,14 @@ public abstract class FlatWindowAbstractIcon
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||
if( background != null ) {
|
||||
// disable antialiasing for background rectangle painting to avoid blury edges when scaled (e.g. at 125% or 175%)
|
||||
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||
|
||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "close" icon for windows (frames and dialogs).
|
||||
@@ -54,7 +55,7 @@ public class FlatWindowCloseIcon
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int ix2 = ix + iwh - 1;
|
||||
int iy2 = iy + iwh - 1;
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "maximize" icon for windows (frames and dialogs).
|
||||
@@ -35,8 +36,11 @@ public class FlatWindowMaximizeIcon
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
|
||||
g.fill( FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||
g.fill( SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix, iy, iwh, iwh, thickness, arc, arc, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "restore" icon for windows (frames and dialogs).
|
||||
@@ -38,18 +39,33 @@ public class FlatWindowRestoreIcon
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||
|
||||
int rwh = (int) (8 * scaleFactor);
|
||||
int ro2 = iwh - rwh;
|
||||
|
||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||
// upper-right rectangle
|
||||
Path2D r1 = SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix + ro2, iy, rwh, rwh, thickness, arc, arcOuter, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||
|
||||
// lower-left rectangle
|
||||
Path2D r2 = SystemInfo.isWindows_11_orLater
|
||||
? FlatUIUtils.createRoundRectangle( ix, iy + ro2, rwh, rwh, thickness, arc, arc, arc, arc )
|
||||
: FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||
|
||||
// paint upper-right rectangle
|
||||
Area area = new Area( r1 );
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||
if( SystemInfo.isWindows_11_orLater ) {
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, (float) (iy + scaleFactor), rwh, rwh ) ) );
|
||||
area.subtract( new Area( new Rectangle2D.Float( (float) (ix + scaleFactor), iy + ro2, rwh, rwh ) ) );
|
||||
} else
|
||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||
g.fill( area );
|
||||
|
||||
// paint lower-left rectangle
|
||||
g.fill( r2 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.resources;
|
||||
|
||||
/**
|
||||
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
||||
* 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.
|
||||
* Otherwise, the compiler outputs a warning because this package is opened in module-info.java.
|
||||
* Also, when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,7 @@ public class FlatArrowButton
|
||||
extends BasicArrowButton
|
||||
implements UIResource
|
||||
{
|
||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
||||
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||
|
||||
protected boolean chevron;
|
||||
protected Color foreground;
|
||||
@@ -211,6 +211,6 @@ public class FlatArrowButton
|
||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||
|
||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, arrowWidth, xOffset, yOffset );
|
||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, getArrowWidth(), getXOffset(), getYOffset() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public class FlatButtonBorder
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||
// In toolbars, use button margin only if explicitly set.
|
||||
// Otherwise use toolbar margin specified in UI defaults.
|
||||
// Otherwise, use toolbar margin specified in UI defaults.
|
||||
Insets margin = (c instanceof AbstractButton)
|
||||
? ((AbstractButton)c).getMargin()
|
||||
: null;
|
||||
|
||||
@@ -38,15 +38,18 @@ import javax.swing.ButtonModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ButtonUI;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicButtonListener;
|
||||
import javax.swing.plaf.basic.BasicButtonUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
@@ -259,6 +262,10 @@ public class FlatButtonUI
|
||||
b.repaint();
|
||||
break;
|
||||
|
||||
case OUTLINE:
|
||||
b.repaint();
|
||||
break;
|
||||
|
||||
case STYLE:
|
||||
case STYLE_CLASS:
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||
@@ -336,7 +343,7 @@ public class FlatButtonUI
|
||||
|
||||
/**
|
||||
* Returns true if the button has an icon but no text,
|
||||
* or it it does not have an icon and the text is either "..." or one character.
|
||||
* or it does not have an icon and the text is either "..." or one character.
|
||||
*/
|
||||
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||
@@ -420,11 +427,21 @@ public class FlatButtonUI
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
boolean isToolBarButton = isToolBarButton( c );
|
||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
||||
float arc = FlatUIUtils.getBorderArc( c );
|
||||
float textFieldArc = 0;
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
// if toolbar button is in leading/trailing component of a text field,
|
||||
// increase toolbar button arc to match text field arc (if necessary)
|
||||
if( isToolBarButton &&
|
||||
FlatClientProperties.clientProperty( c, STYLE_CLASS, "", String.class ).contains( "inTextField" ) )
|
||||
{
|
||||
JTextField textField = (JTextField) SwingUtilities.getAncestorOfClass( JTextField.class, c );
|
||||
if( textField != null )
|
||||
textFieldArc = FlatUIUtils.getBorderArc( textField );
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
@@ -437,8 +454,15 @@ public class FlatButtonUI
|
||||
y += spacing.top;
|
||||
width -= spacing.left + spacing.right;
|
||||
height -= spacing.top + spacing.bottom;
|
||||
|
||||
// reduce text field arc
|
||||
textFieldArc -= spacing.top + spacing.bottom;
|
||||
}
|
||||
|
||||
// increase toolbar button arc to match text field arc (if necessary)
|
||||
if( arc < textFieldArc )
|
||||
arc = textFieldArc;
|
||||
|
||||
// paint shadow
|
||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||
if( paintShadow &&
|
||||
@@ -549,6 +573,9 @@ public class FlatButtonUI
|
||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||
{
|
||||
if( c == null )
|
||||
return enabledColor;
|
||||
|
||||
if( !c.isEnabled() )
|
||||
return disabledColor;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public class FlatCaret
|
||||
|
||||
// if text component is focused, then caret and selection are visible,
|
||||
// but when switching theme, the component does not yet have
|
||||
// an highlighter and the selection is not painted
|
||||
// a highlighter and the selection is not painted
|
||||
// --> make selection temporary invisible later, then the caret
|
||||
// adds selection highlights to the text component highlighter
|
||||
if( isSelectionVisible() ) {
|
||||
@@ -236,7 +236,7 @@ public class FlatCaret
|
||||
if( selectAllOnFocusPolicy == null )
|
||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||
|
||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
return;
|
||||
|
||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||
|
||||
@@ -354,6 +354,7 @@ public class FlatComboBoxUI
|
||||
break;
|
||||
|
||||
case COMPONENT_ROUND_RECT:
|
||||
case OUTLINE:
|
||||
comboBox.repaint();
|
||||
break;
|
||||
|
||||
@@ -699,7 +700,7 @@ public class FlatComboBoxUI
|
||||
return true;
|
||||
|
||||
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
||||
return editorComponent != null && FlatUIUtils.isPermanentFocusOwner( editorComponent );
|
||||
} else
|
||||
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
||||
}
|
||||
|
||||
@@ -275,7 +275,10 @@ public class FlatFileChooserUI
|
||||
|
||||
private boolean doNotUseSystemIcons() {
|
||||
// Java 17 32bit craches on Windows when using system icons
|
||||
return SystemInfo.isWindows && SystemInfo.isJava_17_orLater && !SystemInfo.isX86_64;
|
||||
// fixed in Java 18+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||
return SystemInfo.isWindows &&
|
||||
SystemInfo.isX86 &&
|
||||
(SystemInfo.isJava_17_orLater && !SystemInfo.isJava_18_orLater);
|
||||
}
|
||||
|
||||
//---- class FlatFileView -------------------------------------------------
|
||||
|
||||
@@ -72,7 +72,7 @@ public class FlatListCellBorder
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this borders are always shared for all lists,
|
||||
* Because this border is always shared for all lists,
|
||||
* get border specific style from FlatListUI.
|
||||
*/
|
||||
static <T> T getStyleFromListUI( Component c, Function<FlatListUI, T> f ) {
|
||||
|
||||
@@ -212,7 +212,7 @@ public class FlatListUI
|
||||
/**
|
||||
* Toggle selection colors from focused to inactive and vice versa.
|
||||
*
|
||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
||||
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||
*
|
||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
|
||||
@@ -210,7 +210,7 @@ public class FlatMenuBarUI
|
||||
// check whether:
|
||||
// - TitlePane.unifiedBackground is true and
|
||||
// - menu bar is the "main" menu bar and
|
||||
// - window has custom decorations enabled
|
||||
// - window root pane has custom decoration style
|
||||
|
||||
JRootPane rootPane;
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
@@ -218,7 +218,7 @@ public class FlatMenuBarUI
|
||||
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||
rootPane.getParent() instanceof Window &&
|
||||
rootPane.getJMenuBar() == c &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() );
|
||||
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
|
||||
@@ -35,7 +35,7 @@ import javax.swing.plaf.MenuBarUI;
|
||||
public class FlatMenuItemBorder
|
||||
extends FlatMarginBorder
|
||||
{
|
||||
// only used if parent menubar is not a instance of FlatMenuBarUI
|
||||
// only used if parent menubar is not an instance of FlatMenuBarUI
|
||||
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FlatNativeWindowBorder
|
||||
private static final boolean canUseJBRCustomDecorations =
|
||||
canUseWindowDecorations &&
|
||||
SystemInfo.isJetBrainsJVM_11_orLater &&
|
||||
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, true );
|
||||
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_JETBRAINS_CUSTOM_DECORATIONS, false );
|
||||
|
||||
private static Boolean supported;
|
||||
private static Provider nativeProvider;
|
||||
@@ -313,6 +313,10 @@ public class FlatNativeWindowBorder
|
||||
|
||||
//---- class WindowTopBorder -------------------------------------------
|
||||
|
||||
/**
|
||||
* Window top border used on Windows 10.
|
||||
* No longer needed since Windows 11.
|
||||
*/
|
||||
static class WindowTopBorder
|
||||
extends JBRCustomDecorations.JBRWindowTopBorder
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@ import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicOptionPaneUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.SwingUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -156,7 +157,7 @@ public class FlatOptionPaneUI
|
||||
|
||||
// set icon-message gap
|
||||
if( iconMessageGap > 0 ) {
|
||||
Component iconMessageSeparator = findByName( messageArea, "OptionPane.separator" );
|
||||
Component iconMessageSeparator = SwingUtils.getComponentByName( messageArea, "OptionPane.separator" );
|
||||
if( iconMessageSeparator != null )
|
||||
iconMessageSeparator.setPreferredSize( new Dimension( UIScale.scale( iconMessageGap ), 1 ) );
|
||||
}
|
||||
@@ -236,20 +237,6 @@ public class FlatOptionPaneUI
|
||||
}
|
||||
}
|
||||
|
||||
private Component findByName( Container c, String name ) {
|
||||
for( Component child : c.getComponents() ) {
|
||||
if( name.equals( child.getName() ) )
|
||||
return child;
|
||||
|
||||
if( child instanceof Container ) {
|
||||
Component c2 = findByName( (Container) child, name );
|
||||
if( c2 != null )
|
||||
return c2;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getSizeButtonsToSameWidth() {
|
||||
return sameSizeButtons;
|
||||
|
||||
@@ -18,12 +18,14 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPanelUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
@@ -43,13 +45,12 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*/
|
||||
public class FlatPanelUI
|
||||
extends BasicPanelUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, PropertyChangeListener
|
||||
{
|
||||
// only used via styling (not in UI defaults)
|
||||
/** @since 2 */ @Styleable protected int arc = -1;
|
||||
|
||||
private final boolean shared;
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
@@ -67,9 +68,7 @@ public class FlatPanelUI
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
||||
c, () -> stylePropertyChange( (JPanel) c ), null );
|
||||
c.addPropertyChangeListener( propertyChangeListener );
|
||||
c.addPropertyChangeListener( this );
|
||||
|
||||
installStyle( (JPanel) c );
|
||||
}
|
||||
@@ -78,21 +77,28 @@ public class FlatPanelUI
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
|
||||
c.removePropertyChangeListener( propertyChangeListener );
|
||||
propertyChangeListener = null;
|
||||
c.removePropertyChangeListener( this );
|
||||
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
private void stylePropertyChange( JPanel c ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( c ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
c.updateUI();
|
||||
} else
|
||||
installStyle( c );
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
/** @since 2.0.1 */
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
JPanel c = (JPanel) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( c ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
c.updateUI();
|
||||
} else
|
||||
installStyle( c );
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
|
||||
@@ -28,6 +28,7 @@ import javax.swing.Action;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPasswordField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -38,6 +39,7 @@ import javax.swing.text.Element;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.PasswordView;
|
||||
import javax.swing.text.View;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.icons.FlatCapsLockIcon;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -83,6 +85,9 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatPasswordFieldUI
|
||||
extends FlatTextFieldUI
|
||||
{
|
||||
// used to preserve reveal button state when switching theme
|
||||
private static final String KEY_REVEAL_SELECTED = "FlatLaf.internal.FlatPasswordFieldUI.revealSelected";
|
||||
|
||||
private Character echoChar;
|
||||
|
||||
@Styleable protected boolean showCapsLock;
|
||||
@@ -93,6 +98,7 @@ public class FlatPasswordFieldUI
|
||||
private KeyListener capsLockListener;
|
||||
private boolean capsLockIconShared = true;
|
||||
private JToggleButton revealButton;
|
||||
private boolean uninstallEchoChar;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatPasswordFieldUI();
|
||||
@@ -269,36 +275,65 @@ public class FlatPasswordFieldUI
|
||||
if( !showCapsLock )
|
||||
return false;
|
||||
|
||||
JTextComponent c = getComponent();
|
||||
return FlatUIUtils.isPermanentFocusOwner( c ) &&
|
||||
return FlatUIUtils.isPermanentFocusOwner( getComponent() ) &&
|
||||
Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installRevealButton() {
|
||||
JTextComponent c = getComponent();
|
||||
if( showRevealButton ) {
|
||||
revealButton = createRevealButton();
|
||||
installLayout();
|
||||
c.add( revealButton );
|
||||
getComponent().add( revealButton );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected JToggleButton createRevealButton() {
|
||||
JToggleButton button = new JToggleButton( revealIcon );
|
||||
button.setName( "PasswordField.revealButton" );
|
||||
prepareLeadingOrTrailingComponent( button );
|
||||
button.putClientProperty( FlatClientProperties.STYLE_CLASS, "inTextField revealButton" );
|
||||
if( FlatClientProperties.clientPropertyBoolean( getComponent(), KEY_REVEAL_SELECTED, false ) ) {
|
||||
button.setSelected( true );
|
||||
updateEchoChar( true );
|
||||
}
|
||||
button.addActionListener( e -> {
|
||||
LookAndFeel.installProperty( getComponent(), "echoChar", button.isSelected()
|
||||
? '\0'
|
||||
: (echoChar != null ? echoChar : '*'));
|
||||
boolean selected = button.isSelected();
|
||||
updateEchoChar( selected );
|
||||
getComponent().putClientProperty( KEY_REVEAL_SELECTED, selected );
|
||||
} );
|
||||
return button;
|
||||
}
|
||||
|
||||
private void updateEchoChar( boolean selected ) {
|
||||
char newEchoChar = selected
|
||||
? 0
|
||||
: (echoChar != null ? echoChar : '*');
|
||||
|
||||
JPasswordField c = (JPasswordField) getComponent();
|
||||
LookAndFeel.installProperty( c, "echoChar", newEchoChar );
|
||||
|
||||
// check whether was able to set echo char via LookAndFeel.installProperty()
|
||||
// if not, then echo char was explicitly changed via JPasswordField.setEchoChar()
|
||||
char actualEchoChar = c.getEchoChar();
|
||||
if( actualEchoChar != newEchoChar ) {
|
||||
if( selected && actualEchoChar != 0 ) {
|
||||
// use explicitly set echo char
|
||||
echoChar = actualEchoChar;
|
||||
uninstallEchoChar = true;
|
||||
}
|
||||
|
||||
c.setEchoChar( newEchoChar );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallRevealButton() {
|
||||
if( revealButton != null ) {
|
||||
if( uninstallEchoChar && revealButton.isSelected() )
|
||||
((JPasswordField)getComponent()).setEchoChar( echoChar );
|
||||
|
||||
getComponent().remove( revealButton );
|
||||
revealButton = null;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
@@ -33,6 +35,7 @@ import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.swing.JComponent;
|
||||
@@ -140,7 +143,7 @@ public class FlatPopupFactory
|
||||
* <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 an dialog on the secondary screen and making combobox popup visible.
|
||||
* E.g. when opening a dialog on the secondary screen and making combobox popup visible.
|
||||
* <p>
|
||||
* This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8224608
|
||||
*/
|
||||
@@ -219,7 +222,7 @@ public class FlatPopupFactory
|
||||
* and corrects the y-location so that the tooltip is placed above the mouse location.
|
||||
*/
|
||||
private Point fixToolTipLocation( Component owner, Component contents, int x, int y ) {
|
||||
if( !(contents instanceof JToolTip) || !wasInvokedFromToolTipManager() )
|
||||
if( !(contents instanceof JToolTip) || !wasInvokedFromToolTipManager() || hasTipLocation( owner ) )
|
||||
return null;
|
||||
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
@@ -264,6 +267,35 @@ public class FlatPopupFactory
|
||||
return StackUtils.wasInvokedFrom( ToolTipManager.class.getName(), "showTipWindow", 8 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the owner component returns a tooltip location in
|
||||
* JComponent.getToolTipLocation(MouseEvent).
|
||||
*/
|
||||
private boolean hasTipLocation( Component owner ) {
|
||||
if( !(owner instanceof JComponent) )
|
||||
return false;
|
||||
|
||||
AWTEvent e = EventQueue.getCurrentEvent();
|
||||
MouseEvent me;
|
||||
if( e instanceof MouseEvent )
|
||||
me = (MouseEvent) e;
|
||||
else {
|
||||
// no mouse event available because a timer is used to show the tooltip
|
||||
// --> create mouse event from current mouse location
|
||||
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||
if( pointerInfo == null )
|
||||
return false;
|
||||
|
||||
Point location = new Point( pointerInfo.getLocation());
|
||||
SwingUtilities.convertPointFromScreen( location, owner );
|
||||
me = new MouseEvent( owner, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(),
|
||||
0, location.x, location.y, 0, false );
|
||||
}
|
||||
|
||||
return me.getSource() == owner &&
|
||||
((JComponent)owner).getToolTipLocation( me ) != null;
|
||||
}
|
||||
|
||||
//---- class NonFlashingPopup ---------------------------------------------
|
||||
|
||||
private class NonFlashingPopup
|
||||
|
||||
@@ -16,18 +16,58 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.Popup;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MenuKeyEvent;
|
||||
import javax.swing.event.MenuKeyListener;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
import javax.swing.plaf.ButtonUI;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
||||
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
@@ -41,12 +81,22 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* @uiDefault PopupMenu.foreground Color
|
||||
* @uiDefault PopupMenu.border Border
|
||||
*
|
||||
* <!-- FlatPopupMenuUI -->
|
||||
*
|
||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||
* @uiDefault PopupMenu.scrollArrowColor Color
|
||||
* @uiDefault PopupMenu.hoverScrollArrowBackground Color optional
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPopupMenuUI
|
||||
extends BasicPopupMenuUI
|
||||
implements StyleableUI
|
||||
{
|
||||
/** @since 2.1 */ @Styleable protected String arrowType;
|
||||
/** @since 2.1 */ @Styleable protected Color scrollArrowColor;
|
||||
/** @since 2.1 */ @Styleable protected Color hoverScrollArrowBackground;
|
||||
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
private AtomicBoolean borderShared;
|
||||
@@ -74,11 +124,23 @@ public class FlatPopupMenuUI
|
||||
public void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
arrowType = UIManager.getString( "Component.arrowType" );
|
||||
scrollArrowColor = UIManager.getColor( "PopupMenu.scrollArrowColor" );
|
||||
hoverScrollArrowBackground = UIManager.getColor( "PopupMenu.hoverScrollArrowBackground" );
|
||||
|
||||
LayoutManager layout = popupMenu.getLayout();
|
||||
if( layout == null || layout instanceof UIResource )
|
||||
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
scrollArrowColor = null;
|
||||
hoverScrollArrowBackground = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
@@ -122,6 +184,52 @@ public class FlatPopupMenuUI
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Popup getPopup( JPopupMenu popup, int x, int y ) {
|
||||
// do not add scroller to combobox popups or to popups that already have a scroll pane
|
||||
if( popup instanceof BasicComboPopup ||
|
||||
(popup.getComponentCount() > 0 && popup.getComponent( 0 ) instanceof JScrollPane) )
|
||||
return super.getPopup( popup, x, y );
|
||||
|
||||
// do not add scroller if popup fits into screen
|
||||
Dimension prefSize = popup.getPreferredSize();
|
||||
int screenHeight = getScreenHeightAt( x, y );
|
||||
if( prefSize.height <= screenHeight )
|
||||
return super.getPopup( popup, x, y );
|
||||
|
||||
// create scroller
|
||||
FlatPopupScroller scroller = new FlatPopupScroller( popup );
|
||||
scroller.setPreferredSize( new Dimension( prefSize.width, screenHeight ) );
|
||||
|
||||
// create popup
|
||||
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
||||
return popupFactory.getPopup( popup.getInvoker(), scroller, x, y );
|
||||
}
|
||||
|
||||
private int getScreenHeightAt( int x, int y ) {
|
||||
// find GraphicsConfiguration at popup location (similar to JPopupMenu.getCurrentGraphicsConfiguration())
|
||||
GraphicsConfiguration gc = null;
|
||||
for( GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) {
|
||||
if( device.getType() == GraphicsDevice.TYPE_RASTER_SCREEN ) {
|
||||
GraphicsConfiguration dgc = device.getDefaultConfiguration();
|
||||
if( dgc.getBounds().contains( x, y ) ) {
|
||||
gc = dgc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( gc == null && popupMenu.getInvoker() != null )
|
||||
gc = popupMenu.getInvoker().getGraphicsConfiguration();
|
||||
|
||||
// compute screen height
|
||||
// (always subtract screen insets because there is no API to detect whether
|
||||
// the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar())
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
Rectangle screenBounds = (gc != null) ? gc.getBounds() : new Rectangle( toolkit.getScreenSize() );
|
||||
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
|
||||
return screenBounds.height - screenInsets.top - screenInsets.bottom;
|
||||
}
|
||||
|
||||
//---- class FlatMenuLayout -----------------------------------------------
|
||||
|
||||
protected static class FlatMenuLayout
|
||||
@@ -138,4 +246,206 @@ public class FlatPopupMenuUI
|
||||
return super.preferredLayoutSize( target );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatPopupScroller --------------------------------------------
|
||||
|
||||
private class FlatPopupScroller
|
||||
extends JPanel
|
||||
implements MouseWheelListener, PopupMenuListener, MenuKeyListener
|
||||
{
|
||||
private final JPopupMenu popup;
|
||||
|
||||
private final JScrollPane scrollPane;
|
||||
private final JButton scrollUpButton;
|
||||
private final JButton scrollDownButton;
|
||||
private int unitIncrement;
|
||||
|
||||
FlatPopupScroller( JPopupMenu popup ) {
|
||||
super( new BorderLayout() );
|
||||
this.popup = popup;
|
||||
|
||||
// this panel is required to avoid that JPopupMenu.setLocation() will be invoked
|
||||
// while scrolling, because this would call JPopupMenu.showPopup()
|
||||
JPanel view = new JPanel( new BorderLayout() );
|
||||
view.add( popup, BorderLayout.CENTER );
|
||||
|
||||
scrollPane = new JScrollPane( view, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
|
||||
scrollPane.setBorder( null );
|
||||
|
||||
scrollUpButton = new ArrowButton( SwingConstants.NORTH );
|
||||
scrollDownButton = new ArrowButton( SwingConstants.SOUTH );
|
||||
|
||||
add( scrollPane, BorderLayout.CENTER );
|
||||
add( scrollUpButton, BorderLayout.NORTH );
|
||||
add( scrollDownButton, BorderLayout.SOUTH );
|
||||
|
||||
setBackground( popup.getBackground() );
|
||||
setBorder( popup.getBorder() );
|
||||
popup.setBorder( null );
|
||||
|
||||
popup.addPopupMenuListener( this );
|
||||
popup.addMouseWheelListener( this );
|
||||
popup.addMenuKeyListener( this );
|
||||
|
||||
updateArrowButtons();
|
||||
}
|
||||
|
||||
void scroll( int unitsToScroll ) {
|
||||
if( unitIncrement == 0 )
|
||||
unitIncrement = new JMenuItem( "X" ).getPreferredSize().height;
|
||||
|
||||
JViewport viewport = scrollPane.getViewport();
|
||||
Point viewPosition = viewport.getViewPosition();
|
||||
int newY = viewPosition.y + (unitIncrement * unitsToScroll);
|
||||
if( newY < 0 )
|
||||
newY = 0;
|
||||
else
|
||||
newY = Math.min( newY, viewport.getViewSize().height - viewport.getExtentSize().height );
|
||||
viewport.setViewPosition( new Point( viewPosition.x, newY ) );
|
||||
|
||||
updateArrowButtons();
|
||||
}
|
||||
|
||||
void updateArrowButtons() {
|
||||
JViewport viewport = scrollPane.getViewport();
|
||||
Point viewPosition = viewport.getViewPosition();
|
||||
|
||||
scrollUpButton.setVisible( viewPosition.y > 0 );
|
||||
scrollDownButton.setVisible( viewPosition.y < viewport.getViewSize().height - viewport.getExtentSize().height );
|
||||
}
|
||||
|
||||
//---- interface PopupMenuListener ----
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
|
||||
// restore popup border
|
||||
popup.setBorder( getBorder() );
|
||||
|
||||
popup.removePopupMenuListener( this );
|
||||
popup.removeMouseWheelListener( this );
|
||||
popup.removeMenuKeyListener( this );
|
||||
}
|
||||
|
||||
@Override public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {}
|
||||
@Override public void popupMenuCanceled( PopupMenuEvent e ) {}
|
||||
|
||||
//---- interface MouseWheelListener ----
|
||||
|
||||
/**
|
||||
* Scroll when user rotates mouse wheel.
|
||||
*/
|
||||
@Override
|
||||
public void mouseWheelMoved( MouseWheelEvent e ) {
|
||||
// convert mouse location before scrolling
|
||||
Point mouseLocation = SwingUtilities.convertPoint( (Component) e.getSource(), e.getPoint(), this );
|
||||
|
||||
// scroll
|
||||
scroll( e.getUnitsToScroll() );
|
||||
|
||||
// select menu item at mouse location
|
||||
Component c = SwingUtilities.getDeepestComponentAt( this, mouseLocation.x, mouseLocation.y );
|
||||
if( c instanceof JMenuItem ) {
|
||||
ButtonUI ui = ((JMenuItem)c).getUI();
|
||||
if( ui instanceof BasicMenuItemUI )
|
||||
MenuSelectionManager.defaultManager().setSelectedPath( ((BasicMenuItemUI)ui).getPath() );
|
||||
}
|
||||
|
||||
// this avoids that the popup is closed when running on Java 8
|
||||
// https://bugs.openjdk.java.net/browse/JDK-8075063
|
||||
e.consume();
|
||||
}
|
||||
|
||||
//---- interface MenuKeyListener ----
|
||||
|
||||
/**
|
||||
* Scroll when user presses Up or Down keys.
|
||||
*/
|
||||
@Override
|
||||
public void menuKeyPressed( MenuKeyEvent e ) {
|
||||
// use invokeLater() because menu selection is not yet updated because
|
||||
// this listener is invoked before another listener that updates the menu selection
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( !isDisplayable() )
|
||||
return;
|
||||
|
||||
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
if( path.length == 0 )
|
||||
return;
|
||||
|
||||
// scroll selected menu item to visible area
|
||||
Component c = path[path.length - 1].getComponent();
|
||||
JViewport viewport = scrollPane.getViewport();
|
||||
Point pt = SwingUtilities.convertPoint( c, 0, 0, viewport );
|
||||
viewport.scrollRectToVisible( new Rectangle( pt, c.getSize() ) );
|
||||
|
||||
// update arrow buttons
|
||||
boolean upVisible = scrollUpButton.isVisible();
|
||||
updateArrowButtons();
|
||||
if( !upVisible && scrollUpButton.isVisible() ) {
|
||||
// if "up" button becomes visible, make sure that bottom menu item stays visible
|
||||
Point viewPosition = viewport.getViewPosition();
|
||||
int newY = viewPosition.y + scrollUpButton.getPreferredSize().height;
|
||||
viewport.setViewPosition( new Point( viewPosition.x, newY ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override public void menuKeyTyped( MenuKeyEvent e ) {}
|
||||
@Override public void menuKeyReleased( MenuKeyEvent e ) {}
|
||||
|
||||
//---- class ArrowButton ----------------------------------------------
|
||||
|
||||
private class ArrowButton
|
||||
extends FlatArrowButton
|
||||
implements MouseListener, ActionListener
|
||||
{
|
||||
private Timer timer;
|
||||
|
||||
ArrowButton( int direction ) {
|
||||
super( direction, arrowType, scrollArrowColor, null, null, hoverScrollArrowBackground, null, null );
|
||||
|
||||
addMouseListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g ) {
|
||||
// always fill background to paint over border on HiDPI screens
|
||||
g.setColor( popup.getBackground() );
|
||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||
|
||||
super.paint( g );
|
||||
}
|
||||
|
||||
//---- interface MouseListener ----
|
||||
|
||||
@Override public void mouseClicked( MouseEvent e ) {}
|
||||
@Override public void mousePressed( MouseEvent e ) {}
|
||||
@Override public void mouseReleased( MouseEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent e ) {
|
||||
if( timer == null )
|
||||
timer = new Timer( 50, this );
|
||||
timer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited( MouseEvent e ) {
|
||||
if( timer != null )
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
//---- interface ActionListener ----
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
if( timer != null && !isDisplayable() ) {
|
||||
timer.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
scroll( direction == SwingConstants.NORTH ? -1 : 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ public class FlatRadioButtonUI
|
||||
return infos;
|
||||
}
|
||||
|
||||
private static Insets tempInsets = new Insets( 0, 0, 0, 0 );
|
||||
private static final Insets tempInsets = new Insets( 0, 0, 0, 0 );
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
@@ -212,7 +212,7 @@ public class FlatRadioButtonUI
|
||||
if( focusWidth > 0 ) {
|
||||
// Increase preferred width and height if insets were explicitly reduced (e.g. with
|
||||
// an EmptyBorder) and icon has a focus width, which is not included in icon size.
|
||||
// Otherwise the component may be too small and outer focus border may be cut off.
|
||||
// Otherwise, the component may be too small and outer focus border may be cut off.
|
||||
Insets insets = c.getInsets( tempInsets );
|
||||
size.width += Math.max( focusWidth - insets.left, 0 ) + Math.max( focusWidth - insets.right, 0 );
|
||||
size.height += Math.max( focusWidth - insets.top, 0 ) + Math.max( focusWidth - insets.bottom, 0 );
|
||||
|
||||
@@ -161,13 +161,26 @@ public class FlatRootPaneUI
|
||||
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallDefaults( JRootPane c ) {
|
||||
super.uninstallDefaults( c );
|
||||
|
||||
// uninstall background, foreground and font because not all Lafs set them
|
||||
if( c.isBackgroundSet() && c.getBackground() instanceof UIResource )
|
||||
c.setBackground( null );
|
||||
if( c.isForegroundSet() && c.getForeground() instanceof UIResource )
|
||||
c.setForeground( null );
|
||||
if( c.isFontSet() && c.getFont() instanceof UIResource )
|
||||
c.setFont( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners( JRootPane root ) {
|
||||
super.installListeners( root );
|
||||
|
||||
if( SystemInfo.isJava_9_orLater ) {
|
||||
// On HiDPI screens, where scaling is used, there may be white lines at the
|
||||
// bottom and at the right side of the window when it is initially shown.
|
||||
// On HiDPI screens, where scaling is used, there may be white lines on the
|
||||
// bottom and on the right side of the window when it is initially shown.
|
||||
// This is very disturbing in dark themes, but hard to notice in light themes.
|
||||
// Seems to be a rounding issue when Swing adds dirty region of window
|
||||
// using RepaintManager.nativeAddDirtyRegion().
|
||||
@@ -497,7 +510,7 @@ public class FlatRootPaneUI
|
||||
return;
|
||||
|
||||
Container parent = c.getParent();
|
||||
boolean active = parent instanceof Window ? ((Window)parent).isActive() : false;
|
||||
boolean active = parent instanceof Window && ((Window)parent).isActive();
|
||||
|
||||
g.setColor( FlatUIUtils.deriveColor( active ? activeBorderColor : inactiveBorderColor, baseBorderColor ) );
|
||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
||||
@@ -509,9 +522,7 @@ public class FlatRootPaneUI
|
||||
|
||||
protected boolean isWindowMaximized( Component c ) {
|
||||
Container parent = c.getParent();
|
||||
return parent instanceof Frame
|
||||
? (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
|
||||
: false;
|
||||
return parent instanceof Frame && (((Frame)parent).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatScrollBarUI -->
|
||||
*
|
||||
* @uiDefault ScrollBar.minimumButtonSize Dimension
|
||||
* @uiDefault ScrollBar.trackInsets Insets
|
||||
* @uiDefault ScrollBar.thumbInsets Insets
|
||||
* @uiDefault ScrollBar.trackArc int
|
||||
@@ -83,6 +84,7 @@ public class FlatScrollBarUI
|
||||
// overrides BasicScrollBarUI.supportsAbsolutePositioning (which is private)
|
||||
@Styleable protected boolean allowsAbsolutePositioning;
|
||||
|
||||
/** @since 2.1 */ @Styleable protected Dimension minimumButtonSize;
|
||||
@Styleable protected Insets trackInsets;
|
||||
@Styleable protected Insets thumbInsets;
|
||||
@Styleable protected int trackArc;
|
||||
@@ -142,6 +144,7 @@ public class FlatScrollBarUI
|
||||
|
||||
allowsAbsolutePositioning = super.getSupportsAbsolutePositioning();
|
||||
|
||||
minimumButtonSize = UIManager.getDimension( "ScrollBar.minimumButtonSize" );
|
||||
trackInsets = UIManager.getInsets( "ScrollBar.trackInsets" );
|
||||
thumbInsets = UIManager.getInsets( "ScrollBar.thumbInsets" );
|
||||
trackArc = UIManager.getInt( "ScrollBar.trackArc" );
|
||||
@@ -171,6 +174,7 @@ public class FlatScrollBarUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
minimumButtonSize = null;
|
||||
trackInsets = null;
|
||||
thumbInsets = null;
|
||||
hoverTrackColor = null;
|
||||
@@ -451,7 +455,6 @@ public class FlatScrollBarUI
|
||||
super( direction, type, foreground, disabledForeground,
|
||||
hoverForeground, hoverBackground, pressedForeground, pressedBackground );
|
||||
|
||||
setArrowWidth( FlatArrowButton.DEFAULT_ARROW_WIDTH - 2 );
|
||||
setFocusable( false );
|
||||
setRequestFocusEnabled( false );
|
||||
}
|
||||
@@ -461,6 +464,18 @@ public class FlatScrollBarUI
|
||||
null, hoverButtonBackground, null, pressedButtonBackground );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArrowWidth() {
|
||||
// scale arrow size depending on scroll bar width
|
||||
// (6 is default arrow width; 10 is base scroll bar width)
|
||||
int arrowWidth = Math.round( 6 * (scrollBarWidth / 10f) );
|
||||
|
||||
// compute arrow size that leaves equal space on both sides (arrow is centered)
|
||||
arrowWidth = scrollBarWidth - (((scrollBarWidth - arrowWidth) / 2) * 2);
|
||||
|
||||
return arrowWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color deriveBackground( Color background ) {
|
||||
return FlatUIUtils.deriveColor( background, scrollbar.getBackground() );
|
||||
@@ -469,8 +484,9 @@ public class FlatScrollBarUI
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
if( isShowButtons() ) {
|
||||
int w = UIScale.scale( scrollBarWidth );
|
||||
return new Dimension( w, w );
|
||||
int w = UIScale.scale( Math.max( scrollBarWidth, (minimumButtonSize != null) ? minimumButtonSize.width : 0 ) );
|
||||
int h = UIScale.scale( Math.max( scrollBarWidth, (minimumButtonSize != null) ? minimumButtonSize.height : 0 ) );
|
||||
return new Dimension( w, h );
|
||||
} else
|
||||
return new Dimension();
|
||||
}
|
||||
|
||||
@@ -291,6 +291,10 @@ public class FlatScrollPaneUI
|
||||
}
|
||||
break;
|
||||
|
||||
case FlatClientProperties.OUTLINE:
|
||||
scrollpane.repaint();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
installStyle();
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
@@ -28,6 +29,7 @@ import javax.swing.JSeparator;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicSeparatorUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
@@ -50,7 +52,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
*/
|
||||
public class FlatSeparatorUI
|
||||
extends BasicSeparatorUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, PropertyChangeListener
|
||||
{
|
||||
@Styleable protected int height;
|
||||
@Styleable protected int stripeWidth;
|
||||
@@ -58,7 +60,6 @@ public class FlatSeparatorUI
|
||||
|
||||
private final boolean shared;
|
||||
private boolean defaults_initialized = false;
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
@@ -109,28 +110,33 @@ public class FlatSeparatorUI
|
||||
protected void installListeners( JSeparator s ) {
|
||||
super.installListeners( s );
|
||||
|
||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
||||
s, () -> stylePropertyChange( s ), null );
|
||||
s.addPropertyChangeListener( propertyChangeListener );
|
||||
s.addPropertyChangeListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( JSeparator s ) {
|
||||
super.uninstallListeners( s );
|
||||
|
||||
s.removePropertyChangeListener( propertyChangeListener );
|
||||
propertyChangeListener = null;
|
||||
s.removePropertyChangeListener( this );
|
||||
}
|
||||
|
||||
private void stylePropertyChange( JSeparator s ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
s.revalidate();
|
||||
s.repaint();
|
||||
/** @since 2.0.1 */
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
JSeparator s = (JSeparator) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
s.revalidate();
|
||||
s.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
|
||||
@@ -234,7 +234,7 @@ public class FlatSliderUI
|
||||
return -1;
|
||||
|
||||
// use default font (instead of slider font) because the slider font size
|
||||
// may be different to label font size, but we want align the track/thumb with labels
|
||||
// may be different to label font size, but we want to align the track/thumb with labels
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
if( font == null )
|
||||
font = slider.getFont();
|
||||
|
||||
@@ -293,9 +293,7 @@ public class FlatSpinnerUI
|
||||
return true;
|
||||
|
||||
JTextField textField = getEditorTextField( spinner.getEditor() );
|
||||
return (textField != null)
|
||||
? FlatUIUtils.isPermanentFocusOwner( textField )
|
||||
: false;
|
||||
return textField != null && FlatUIUtils.isPermanentFocusOwner( textField );
|
||||
}
|
||||
|
||||
protected Color getBackground( boolean enabled ) {
|
||||
@@ -447,7 +445,7 @@ public class FlatSpinnerUI
|
||||
Insets padding = scale( FlatSpinnerUI.this.padding );
|
||||
Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 );
|
||||
|
||||
// the arrows width is the same as the inner height so that the arrows area is square
|
||||
// the arrow buttons width is the same as the inner height so that the arrow buttons area is square
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( spinner, FlatSpinnerUI.this.minimumWidth );
|
||||
int innerHeight = editorSize.height + padding.top + padding.bottom;
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( spinner );
|
||||
@@ -538,6 +536,7 @@ public class FlatSpinnerUI
|
||||
break;
|
||||
|
||||
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
||||
case FlatClientProperties.OUTLINE:
|
||||
spinner.repaint();
|
||||
break;
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ public class FlatStylingSupport
|
||||
* @param key the name of the field
|
||||
* @param value the new value
|
||||
* @return the old value of the field
|
||||
* @throws UnknownStyleException if object does not have a annotated field with given name
|
||||
* @throws UnknownStyleException if object does not have an annotated field with given name
|
||||
* @throws IllegalArgumentException if value type does not fit to expected type
|
||||
*/
|
||||
public static Object applyToAnnotatedObject( Object obj, String key, Object value )
|
||||
@@ -517,7 +517,7 @@ public class FlatStylingSupport
|
||||
* @param key the name of the field
|
||||
* @param value the new value
|
||||
* @return the old value of the field
|
||||
* @throws UnknownStyleException if object does not have a annotated field with given name
|
||||
* @throws UnknownStyleException if object does not have an annotated field with given name
|
||||
* @throws IllegalArgumentException if value type does not fit to expected type
|
||||
*/
|
||||
public static Object applyToAnnotatedObjectOrComponent( Object obj, Object comp, String key, Object value )
|
||||
|
||||
@@ -650,7 +650,7 @@ public class FlatTabbedPaneUI
|
||||
case "tabIconPlacement": value = parseTabIconPlacement( (String) value ); break;
|
||||
}
|
||||
} else {
|
||||
Object oldValue = null;
|
||||
Object oldValue;
|
||||
switch( key ) {
|
||||
// BasicTabbedPaneUI
|
||||
case "tabInsets": oldValue = tabInsets; tabInsets = (Insets) value; return oldValue;
|
||||
@@ -1841,7 +1841,7 @@ public class FlatTabbedPaneUI
|
||||
super( direction, arrowType,
|
||||
FlatTabbedPaneUI.this.foreground, FlatTabbedPaneUI.this.disabledForeground,
|
||||
null, buttonHoverBackground, null, buttonPressedBackground );
|
||||
setArrowWidth( 10 );
|
||||
setArrowWidth( 11 );
|
||||
}
|
||||
|
||||
protected void updateStyle() {
|
||||
@@ -1983,7 +1983,7 @@ public class FlatTabbedPaneUI
|
||||
}
|
||||
|
||||
protected JMenuItem createTabMenuItem( int tabIndex ) {
|
||||
// search for tab name in this places
|
||||
// search for tab name in these places
|
||||
// 1. tab title
|
||||
// 2. text of label or text component in custom tab component (including children)
|
||||
// 3. accessible name of tab
|
||||
@@ -2016,7 +2016,7 @@ public class FlatTabbedPaneUI
|
||||
menuItem.setOpaque( true );
|
||||
}
|
||||
|
||||
if( !tabPane.isEnabledAt( tabIndex ) )
|
||||
if( !tabPane.isEnabled() || !tabPane.isEnabledAt( tabIndex ) )
|
||||
menuItem.setEnabled( false );
|
||||
|
||||
menuItem.addActionListener( e -> selectTab( tabIndex ) );
|
||||
@@ -2412,7 +2412,7 @@ public class FlatTabbedPaneUI
|
||||
if( tabPane == null || tabViewport == null )
|
||||
return;
|
||||
|
||||
if( !scrolled || tabViewport == null )
|
||||
if( !scrolled )
|
||||
return;
|
||||
scrolled = false;
|
||||
|
||||
@@ -2525,9 +2525,7 @@ public class FlatTabbedPaneUI
|
||||
setRolloverTab( tabIndex );
|
||||
|
||||
// check whether mouse hit tab close area
|
||||
boolean hitClose = isTabClosable( tabIndex )
|
||||
? getTabCloseHitArea( tabIndex ).contains( x, y )
|
||||
: false;
|
||||
boolean hitClose = isTabClosable( tabIndex ) && getTabCloseHitArea( tabIndex ).contains( x, y );
|
||||
if( e.getID() == MouseEvent.MOUSE_PRESSED )
|
||||
pressedTabIndex = hitClose ? tabIndex : -1;
|
||||
setRolloverTabClose( hitClose );
|
||||
@@ -2550,8 +2548,7 @@ public class FlatTabbedPaneUI
|
||||
if( tabIndex == lastTipTabIndex )
|
||||
return; // closeTip already set
|
||||
|
||||
if( tabIndex != lastTipTabIndex )
|
||||
restoreTabToolTip();
|
||||
restoreTabToolTip();
|
||||
|
||||
lastTipTabIndex = tabIndex;
|
||||
lastTip = tabPane.getToolTipTextAt( lastTipTabIndex );
|
||||
|
||||
@@ -72,7 +72,7 @@ public class FlatTableCellBorder
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this borders are always shared for all tables,
|
||||
* Because this border is always shared for all tables,
|
||||
* get border specific style from FlatTableUI.
|
||||
*/
|
||||
static <T> T getStyleFromTableUI( Component c, Function<FlatTableUI, T> f ) {
|
||||
|
||||
@@ -288,7 +288,7 @@ public class FlatTableUI
|
||||
/**
|
||||
* Toggle selection colors from focused to inactive and vice versa.
|
||||
*
|
||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
||||
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||
*
|
||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
|
||||
@@ -232,6 +232,7 @@ public class FlatTextFieldUI
|
||||
switch( e.getPropertyName() ) {
|
||||
case PLACEHOLDER_TEXT:
|
||||
case COMPONENT_ROUND_RECT:
|
||||
case OUTLINE:
|
||||
case TEXT_FIELD_PADDING:
|
||||
c.repaint();
|
||||
break;
|
||||
@@ -368,7 +369,7 @@ public class FlatTextFieldUI
|
||||
if( !(oldBackground instanceof UIResource) )
|
||||
return;
|
||||
|
||||
// do not update background if it currently has a unknown color (assigned from outside)
|
||||
// do not update background if it currently has an unknown color (assigned from outside)
|
||||
if( oldBackground != background &&
|
||||
oldBackground != disabledBackground &&
|
||||
oldBackground != inactiveBackground &&
|
||||
@@ -609,7 +610,7 @@ debug*/
|
||||
* Returns the rectangle used to paint leading and trailing icons.
|
||||
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
||||
* right margin if the text field has leading or trailing icons or components.
|
||||
* Also the preferred widths of leading and trailing components are removed.
|
||||
* Also, the preferred widths of leading and trailing components are removed.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@@ -764,6 +765,7 @@ debug*/
|
||||
/** @since 2 */
|
||||
protected JComponent createClearButton() {
|
||||
JButton button = new JButton();
|
||||
button.setName( "TextField.clearButton" );
|
||||
button.putClientProperty( STYLE_CLASS, "clearButton" );
|
||||
button.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||
button.setCursor( Cursor.getDefaultCursor() );
|
||||
@@ -825,15 +827,20 @@ debug*/
|
||||
/** @since 2 */
|
||||
protected void prepareLeadingOrTrailingComponent( JComponent c ) {
|
||||
c.putClientProperty( STYLE_CLASS, "inTextField" );
|
||||
c.setCursor( Cursor.getDefaultCursor() );
|
||||
|
||||
if( c instanceof JButton || c instanceof JToggleButton )
|
||||
if( c instanceof JButton || c instanceof JToggleButton ) {
|
||||
c.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||
else if( c instanceof JToolBar ) {
|
||||
|
||||
if( !c.isCursorSet() )
|
||||
c.setCursor( Cursor.getDefaultCursor() );
|
||||
} else if( c instanceof JToolBar ) {
|
||||
for( Component child : c.getComponents() ) {
|
||||
if( child instanceof JComponent )
|
||||
((JComponent)child).putClientProperty( STYLE_CLASS, "inTextField" );
|
||||
}
|
||||
|
||||
if( !c.isCursorSet() )
|
||||
c.setCursor( Cursor.getDefaultCursor() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,6 +944,7 @@ debug*/
|
||||
((LayoutManager2)delegate).invalidateLayout( target );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatDocumentListener -----------------------------------------
|
||||
|
||||
private class FlatDocumentListener
|
||||
|
||||
@@ -248,7 +248,7 @@ public class FlatTitlePane
|
||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||
// but at this time the owner window type is unknown (not yet added)
|
||||
// so we add the iconify/maximize/restore buttons and they are shown
|
||||
// so we add the iconify/maximize/restore buttons, and they are shown
|
||||
// later in frameStateChanged(), which is invoked from addNotify()
|
||||
|
||||
buttonPanel.add( iconifyButton );
|
||||
@@ -420,7 +420,7 @@ public class FlatTitlePane
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this title pane currently has an visible and embedded menubar.
|
||||
* Returns whether this title pane currently has a visible and embedded menubar.
|
||||
*/
|
||||
protected boolean hasVisibleEmbeddedMenuBar( JMenuBar menuBar ) {
|
||||
return menuBar != null && menuBar.isVisible() && isMenuBarEmbedded();
|
||||
@@ -615,7 +615,7 @@ debug*/
|
||||
int maximizedWidth = screenBounds.width;
|
||||
int maximizedHeight = screenBounds.height;
|
||||
|
||||
if( !isMaximizedBoundsFixed() ) {
|
||||
if( SystemInfo.isWindows && !isMaximizedBoundsFixed() ) {
|
||||
// on Java 8 to 14, maximized x,y are 0,0 based on all screens in a multi-screen environment
|
||||
maximizedX = 0;
|
||||
maximizedY = 0;
|
||||
@@ -772,7 +772,7 @@ debug*/
|
||||
if( horizontalGlue != null ) {
|
||||
// If menu bar is embedded and contains a horizontal glue component,
|
||||
// then split the hit test spot into two spots so that
|
||||
// the glue component area can used to move the window.
|
||||
// the glue component area can be used to move the window.
|
||||
|
||||
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
|
||||
int x2 = glueLocation.x + horizontalGlue.getWidth();
|
||||
@@ -854,7 +854,7 @@ debug*/
|
||||
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) )
|
||||
insets.bottom += UIScale.scale( 1 );
|
||||
|
||||
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||
insets = FlatUIUtils.addInsets( insets, WindowTopBorder.getInstance().getBorderInsets() );
|
||||
|
||||
return insets;
|
||||
@@ -873,7 +873,7 @@ debug*/
|
||||
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||
}
|
||||
|
||||
if( hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() && !isWindowMaximized( c ) )
|
||||
WindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@@ -883,9 +883,7 @@ debug*/
|
||||
}
|
||||
|
||||
protected boolean isWindowMaximized( Component c ) {
|
||||
return window instanceof Frame
|
||||
? (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0
|
||||
: false;
|
||||
return window instanceof Frame && (((Frame) window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,7 +909,7 @@ debug*/
|
||||
boolean center = hasEmbeddedMenuBar ? centerTitleIfMenuBarEmbedded : centerTitle;
|
||||
if( center ) {
|
||||
// If window is wide enough, center title within window bounds.
|
||||
// Otherwise leave it centered within free space (label bounds).
|
||||
// Otherwise, leave it centered within free space (label bounds).
|
||||
int centeredTextX = ((l.getParent().getWidth() - textWidth) / 2) - l.getX();
|
||||
if( centeredTextX >= gap && centeredTextX + textWidth <= labelWidth - gap )
|
||||
textX = centeredTextX;
|
||||
@@ -966,7 +964,7 @@ debug*/
|
||||
activeChanged( true );
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
|
||||
if( hasNativeCustomDecoration() )
|
||||
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() )
|
||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||
|
||||
repaintWindowBorder();
|
||||
@@ -977,7 +975,7 @@ debug*/
|
||||
activeChanged( false );
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
|
||||
if( hasNativeCustomDecoration() )
|
||||
if( !SystemInfo.isWindows_11_orLater && hasNativeCustomDecoration() )
|
||||
WindowTopBorder.getInstance().repaintBorder( FlatTitlePane.this );
|
||||
|
||||
repaintWindowBorder();
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JComponent;
|
||||
@@ -164,11 +163,7 @@ public class FlatToggleButtonUI
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
Map<String, Class<?>> infos = super.getStyleableInfos( c );
|
||||
Iterator<String> it = infos.keySet().iterator();
|
||||
while( it.hasNext() ) {
|
||||
if( it.next().startsWith( "help." ) )
|
||||
it.remove();
|
||||
}
|
||||
infos.keySet().removeIf( s -> s.startsWith( "help." ) );
|
||||
return infos;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
@@ -31,6 +32,7 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
@@ -47,7 +49,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
*/
|
||||
public class FlatToolBarSeparatorUI
|
||||
extends BasicToolBarSeparatorUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, PropertyChangeListener
|
||||
{
|
||||
private static final int LINE_WIDTH = 1;
|
||||
|
||||
@@ -56,7 +58,6 @@ public class FlatToolBarSeparatorUI
|
||||
|
||||
private final boolean shared;
|
||||
private boolean defaults_initialized = false;
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
@@ -105,28 +106,33 @@ public class FlatToolBarSeparatorUI
|
||||
protected void installListeners( JSeparator s ) {
|
||||
super.installListeners( s );
|
||||
|
||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
||||
s, () -> stylePropertyChange( s ), null );
|
||||
s.addPropertyChangeListener( propertyChangeListener );
|
||||
s.addPropertyChangeListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( JSeparator s ) {
|
||||
super.uninstallListeners( s );
|
||||
|
||||
s.removePropertyChangeListener( propertyChangeListener );
|
||||
propertyChangeListener = null;
|
||||
s.removePropertyChangeListener( this );
|
||||
}
|
||||
|
||||
private void stylePropertyChange( JSeparator s ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
s.revalidate();
|
||||
s.repaint();
|
||||
/** @since 2.0.1 */
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.STYLE:
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
JSeparator s = (JSeparator) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
s.revalidate();
|
||||
s.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
|
||||
@@ -282,7 +282,7 @@ public class FlatToolBarUI
|
||||
return comboBox.getUI().isFocusTraversable( comboBox );
|
||||
}
|
||||
|
||||
// check whether component has a empty input map to skip components that
|
||||
// check whether component has an empty input map to skip components that
|
||||
// are focusable, but do nothing when focused (e.g. JLabel)
|
||||
// see LayoutFocusTraversalPolicy.accept()
|
||||
if( c instanceof JComponent ) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
@@ -49,9 +50,8 @@ import com.formdev.flatlaf.util.StringUtils;
|
||||
*/
|
||||
public class FlatToolTipUI
|
||||
extends BasicToolTipUI
|
||||
implements PropertyChangeListener
|
||||
{
|
||||
private static PropertyChangeListener sharedPropertyChangedListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.createSharedUI( FlatToolTipUI.class, FlatToolTipUI::new );
|
||||
}
|
||||
@@ -68,24 +68,24 @@ public class FlatToolTipUI
|
||||
protected void installListeners( JComponent c ) {
|
||||
super.installListeners( c );
|
||||
|
||||
if( sharedPropertyChangedListener == null ) {
|
||||
sharedPropertyChangedListener = e -> {
|
||||
String name = e.getPropertyName();
|
||||
if( name == "tiptext" || name == "font" || name == "foreground" ) {
|
||||
JToolTip toolTip = (JToolTip) e.getSource();
|
||||
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
c.addPropertyChangeListener( sharedPropertyChangedListener );
|
||||
c.addPropertyChangeListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( JComponent c ) {
|
||||
super.uninstallListeners( c );
|
||||
|
||||
c.removePropertyChangeListener( sharedPropertyChangedListener );
|
||||
c.removePropertyChangeListener( this );
|
||||
}
|
||||
|
||||
/** @since 2.0.1 */
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
String name = e.getPropertyName();
|
||||
if( name == "tiptext" || name == "font" || name == "foreground" ) {
|
||||
JToolTip toolTip = (JToolTip) e.getSource();
|
||||
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,7 +71,7 @@ public class FlatUIUtils
|
||||
public static final boolean MAC_USE_QUARTZ = Boolean.getBoolean( "apple.awt.graphics.UseQuartz" );
|
||||
|
||||
private static boolean useSharedUIs = true;
|
||||
private static WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
||||
private static final WeakHashMap<LookAndFeel, IdentityHashMap<Object, ComponentUI>> sharedUIinstances = new WeakHashMap<>();
|
||||
|
||||
public static Rectangle addInsets( Rectangle r, Insets insets ) {
|
||||
return new Rectangle(
|
||||
@@ -777,8 +777,8 @@ public class FlatUIUtils
|
||||
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
|
||||
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
|
||||
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
|
||||
* @param xOffset a offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||
* @param yOffset a offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||
* @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||
* @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
@@ -786,13 +786,15 @@ public class FlatUIUtils
|
||||
int direction, boolean chevron, int arrowSize, float xOffset, float yOffset )
|
||||
{
|
||||
// compute arrow width/height
|
||||
int aw = UIScale.scale( arrowSize + (chevron ? 0 : 1) );
|
||||
int ah = UIScale.scale( (arrowSize / 2) + (chevron ? 0 : 1) );
|
||||
// - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5)
|
||||
// - make triangle arrows one pixel taller (and round height up) to make them look stronger
|
||||
float aw = UIScale.scale( arrowSize + (chevron ? -1 : 0) );
|
||||
float ah = chevron ? (aw / 2) : UIScale.scale( (arrowSize / 2) + 1 );
|
||||
|
||||
// rotate arrow width/height for horizontal directions
|
||||
boolean vert = (direction == SwingConstants.NORTH || direction == SwingConstants.SOUTH);
|
||||
if( !vert ) {
|
||||
int temp = aw;
|
||||
float temp = aw;
|
||||
aw = ah;
|
||||
ah = temp;
|
||||
}
|
||||
@@ -804,19 +806,19 @@ public class FlatUIUtils
|
||||
// compute arrow location
|
||||
float ox = ((width - (aw + extra)) / 2f) + UIScale.scale( xOffset );
|
||||
float oy = ((height - (ah + extra)) / 2f) + UIScale.scale( yOffset );
|
||||
int ax = x + ((direction == SwingConstants.WEST) ? -Math.round( -ox ) : Math.round( ox ));
|
||||
int ay = y + ((direction == SwingConstants.NORTH) ? -Math.round( -oy ) : Math.round( oy ));
|
||||
float ax = x + ((direction == SwingConstants.WEST) ? -Math.round( -(ox + aw) ) - aw : Math.round( ox ));
|
||||
float ay = y + ((direction == SwingConstants.NORTH) ? -Math.round( -(oy + ah) ) - ah : Math.round( oy ));
|
||||
|
||||
// paint arrow
|
||||
g.translate( ax, ay );
|
||||
/*debug
|
||||
debugPaintArrow( g, Color.red, vert, aw + extra, ah + extra );
|
||||
debugPaintArrow( g, Color.red, vert, Math.round( aw + extra ), Math.round( ah + extra ) );
|
||||
debug*/
|
||||
Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
|
||||
if( chevron ) {
|
||||
Stroke oldStroke = g.getStroke();
|
||||
g.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
||||
g.draw( arrowShape );
|
||||
drawShapePure( g, arrowShape );
|
||||
g.setStroke( oldStroke );
|
||||
} else {
|
||||
// triangle
|
||||
@@ -828,7 +830,7 @@ debug*/
|
||||
/**
|
||||
* Creates a chevron or triangle arrow shape for the given direction and size.
|
||||
* <p>
|
||||
* The chevron shape is a open path that can be painted with {@link Graphics2D#draw(Shape)}.
|
||||
* The chevron shape is an open path that can be painted with {@link Graphics2D#draw(Shape)}.
|
||||
* The triangle shape is a close path that can be painted with {@link Graphics2D#fill(Shape)}.
|
||||
*
|
||||
* @param direction the arrow direction ({@link SwingConstants#NORTH}, {@link SwingConstants#SOUTH}
|
||||
@@ -880,7 +882,7 @@ debug*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a open or closed path for the given points.
|
||||
* Creates an open or closed path for the given points.
|
||||
*/
|
||||
public static Path2D createPath( boolean close, double... points ) {
|
||||
Path2D path = new Path2D.Float();
|
||||
@@ -892,6 +894,23 @@ debug*/
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the given shape with disabled stroke normalization.
|
||||
* The x/y coordinates of the shape are translated by a half pixel.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public static void drawShapePure( Graphics2D g, Shape shape ) {
|
||||
Object oldStrokeControl = g.getRenderingHint( RenderingHints.KEY_STROKE_CONTROL );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
|
||||
g.translate( 0.5, 0.5 );
|
||||
g.draw( shape );
|
||||
g.translate( -0.5, -0.5 );
|
||||
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, oldStrokeControl );
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the given string at the specified location.
|
||||
* The provided component is used to query text properties and anti-aliasing hints.
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
@@ -43,6 +44,7 @@ import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -231,8 +233,15 @@ public abstract class FlatWindowResizer
|
||||
{
|
||||
protected Window window;
|
||||
|
||||
private final boolean limitResizeToScreenBounds;
|
||||
|
||||
public WindowResizer( JRootPane rootPane ) {
|
||||
super( rootPane );
|
||||
|
||||
// On Linux, limit window resizing to screen bounds because otherwise
|
||||
// there would be a strange effect when the mouse is moved over a sidebar
|
||||
// while resizing and the opposite window side is also resized.
|
||||
limitResizeToScreenBounds = SystemInfo.isLinux;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -289,11 +298,19 @@ public abstract class FlatWindowResizer
|
||||
|
||||
@Override
|
||||
protected boolean limitToParentBounds() {
|
||||
return false;
|
||||
return limitResizeToScreenBounds && window != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rectangle getParentBounds() {
|
||||
if( limitResizeToScreenBounds && window != null ) {
|
||||
GraphicsConfiguration gc = window.getGraphicsConfiguration();
|
||||
Rectangle bounds = gc.getBounds();
|
||||
Insets insets = window.getToolkit().getScreenInsets( gc );
|
||||
return new Rectangle( bounds.x + insets.left, bounds.y + insets.top,
|
||||
bounds.width - insets.left - insets.right,
|
||||
bounds.height - insets.top - insets.bottom );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -385,7 +402,7 @@ public abstract class FlatWindowResizer
|
||||
|
||||
@Override
|
||||
protected Rectangle getParentBounds() {
|
||||
return getFrame().getParent().getBounds();
|
||||
return new Rectangle( getFrame().getParent().getSize() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -579,8 +596,8 @@ debug*/
|
||||
// top
|
||||
if( resizeDir == N_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR ) {
|
||||
newBounds.y = yOnScreen - dragTopOffset;
|
||||
if( limitToParentBounds() && newBounds.y < 0 )
|
||||
newBounds.y = 0;
|
||||
if( limitToParentBounds() )
|
||||
newBounds.y = Math.max( newBounds.y, getParentBounds().y );
|
||||
newBounds.height += (oldBounds.y - newBounds.y);
|
||||
}
|
||||
|
||||
@@ -597,8 +614,8 @@ debug*/
|
||||
// left
|
||||
if( resizeDir == W_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR ) {
|
||||
newBounds.x = xOnScreen - dragLeftOffset;
|
||||
if( limitToParentBounds() && newBounds.x < 0 )
|
||||
newBounds.x = 0;
|
||||
if( limitToParentBounds() )
|
||||
newBounds.x = Math.max( newBounds.x, getParentBounds().x );
|
||||
newBounds.width += (oldBounds.x - newBounds.x);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.awt.Window;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
@@ -37,6 +38,7 @@ import javax.swing.Timer;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.EventListenerList;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.NativeLibrary;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
@@ -114,11 +116,7 @@ class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
}
|
||||
|
||||
String libraryName = "com/formdev/flatlaf/natives/flatlaf-windows-x86";
|
||||
if( SystemInfo.isX86_64 )
|
||||
libraryName += "_64";
|
||||
|
||||
nativeLibrary = new NativeLibrary( libraryName, null, true );
|
||||
nativeLibrary = createNativeLibrary();
|
||||
}
|
||||
|
||||
// check whether native library was successfully loaded
|
||||
@@ -131,6 +129,23 @@ class FlatWindowsNativeWindowBorder
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static NativeLibrary createNativeLibrary() {
|
||||
String libraryName = "flatlaf-windows-x86";
|
||||
if( SystemInfo.isX86_64 )
|
||||
libraryName += "_64";
|
||||
|
||||
String libraryPath = System.getProperty( FlatSystemProperties.NATIVE_LIBRARY_PATH );
|
||||
if( libraryPath != null ) {
|
||||
File libraryFile = new File( libraryPath, libraryName + ".dll" );
|
||||
if( libraryFile.exists() )
|
||||
return new NativeLibrary( libraryFile, true );
|
||||
else
|
||||
LoggingFacade.INSTANCE.logSevere( "Did not find external library " + libraryFile + ", using extracted library instead", null );
|
||||
}
|
||||
|
||||
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
|
||||
}
|
||||
|
||||
private FlatWindowsNativeWindowBorder() {
|
||||
}
|
||||
|
||||
@@ -140,7 +155,7 @@ class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the window whether the application wants use custom decorations.
|
||||
* Tell the window whether the application wants to use custom decorations.
|
||||
* If {@code true}, the Windows 10 title bar is hidden (including minimize,
|
||||
* maximize and close buttons), but not the resize borders (including drop shadow).
|
||||
*/
|
||||
|
||||
@@ -284,7 +284,7 @@ public class JBRCustomDecorations
|
||||
@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() : false;
|
||||
boolean active = window != null && window.isActive();
|
||||
|
||||
// paint top border
|
||||
// - in light themes
|
||||
@@ -298,7 +298,7 @@ public class JBRCustomDecorations
|
||||
}
|
||||
|
||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
g.drawRect( x, y, width - 1, 0 );
|
||||
g.fillRect( x, y, width, 1 );
|
||||
}
|
||||
|
||||
void repaintBorder( Component c ) {
|
||||
|
||||
@@ -59,7 +59,7 @@ import com.formdev.flatlaf.util.Animator.Interpolator;
|
||||
* </pre>
|
||||
*
|
||||
* Animation works only if the component passed to {@link #paintIcon(Component, Graphics, int, int)}
|
||||
* is a instance of {@link JComponent}.
|
||||
* is an instance of {@link JComponent}.
|
||||
* A client property is set on the component to store the animation state.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -68,7 +68,7 @@ public interface AnimatedIcon
|
||||
extends Icon
|
||||
{
|
||||
@Override
|
||||
public default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
default void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
AnimationSupport.paintIcon( this, c, g, x, y );
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ public class ColorFunctions
|
||||
return color1;
|
||||
if( weight <= 0 )
|
||||
return color2;
|
||||
if( color1.equals( color2 ) )
|
||||
return color1;
|
||||
|
||||
int r1 = color1.getRed();
|
||||
int g1 = color1.getGreen();
|
||||
@@ -196,6 +198,9 @@ public class ColorFunctions
|
||||
: (float) Math.pow( (value + 0.055) / 1.055, 2.4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given color functions to the given color and returns the new color.
|
||||
*/
|
||||
public static Color applyFunctions( Color color, ColorFunction... functions ) {
|
||||
// if having only a single function of type Mix, then avoid four unnecessary conversions:
|
||||
// 1. RGB to HSL in this method
|
||||
@@ -221,6 +226,9 @@ public class ColorFunctions
|
||||
return HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the given value between 0 and 100.
|
||||
*/
|
||||
public static float clamp( float value ) {
|
||||
return (value < 0)
|
||||
? 0
|
||||
|
||||
@@ -47,7 +47,7 @@ public class DerivedColor
|
||||
Color result = ColorFunctions.applyFunctions( baseColor, functions );
|
||||
|
||||
// if the result is equal to the default color, then the original base color
|
||||
// was passed and we can cache this to avoid color calculations
|
||||
// was passed, and we can cache this to avoid color calculations
|
||||
if( !hasBaseOfDefaultColor && result.getRGB() == this.getRGB() ) {
|
||||
hasBaseOfDefaultColor = true;
|
||||
baseOfDefaultColorRGB = baseColor.getRGB();
|
||||
|
||||
@@ -76,7 +76,7 @@ public class HSLColor
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HSLColor object using an an array containing the
|
||||
* Create a HSLColor object using an array containing the
|
||||
* individual HSL values and with a default alpha value of 1.
|
||||
*
|
||||
* @param hsl array containing HSL values
|
||||
@@ -87,7 +87,7 @@ public class HSLColor
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HSLColor object using an an array containing the
|
||||
* Create a HSLColor object using an array containing the
|
||||
* individual HSL values.
|
||||
*
|
||||
* @param hsl array containing HSL values
|
||||
@@ -291,7 +291,7 @@ public class HSLColor
|
||||
|
||||
// Calculate the Saturation
|
||||
|
||||
float s = 0;
|
||||
float s;
|
||||
|
||||
if (max == min)
|
||||
s = 0;
|
||||
@@ -386,7 +386,7 @@ public class HSLColor
|
||||
s /= 100f;
|
||||
l /= 100f;
|
||||
|
||||
float q = 0;
|
||||
float q;
|
||||
|
||||
if (l < 0.5)
|
||||
q = l * (1 + s);
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
||||
public class HiDPIUtils
|
||||
{
|
||||
public interface Painter {
|
||||
public void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||
void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||
}
|
||||
|
||||
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
|
||||
@@ -114,7 +114,7 @@ public class HiDPIUtils
|
||||
* painted too far down on some operating systems.
|
||||
* The higher the system scale factor is, the more.
|
||||
* <p>
|
||||
* This methods computes a correction value for the Y position.
|
||||
* This method computes a correction value for the Y position.
|
||||
*/
|
||||
public static float computeTextYCorrection( Graphics2D g ) {
|
||||
if( !useTextYCorrection() || !SystemInfo.isWindows )
|
||||
|
||||
@@ -89,7 +89,7 @@ public class JavaCompatibility
|
||||
getClippedStringMethod = cls.getMethod( SystemInfo.isJava_9_orLater
|
||||
? "getClippedString"
|
||||
: "clipStringIfNecessary",
|
||||
new Class[] { JComponent.class, FontMetrics.class, String.class, int.class } );
|
||||
JComponent.class, FontMetrics.class, String.class, int.class );
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
throw new RuntimeException( ex );
|
||||
|
||||
@@ -72,7 +72,7 @@ public class MultiResolutionImageSupport
|
||||
* <p>
|
||||
* The given dimensions array is only used for {@link #getResolutionVariants(Image)}.
|
||||
* The producer function may be invoked with any dimension (that is not contained in
|
||||
* dimensions array) and is expected to produce a image for the passed in dimension.
|
||||
* dimensions array) and is expected to produce an image for the passed in dimension.
|
||||
*
|
||||
* @param baseImageIndex index of the base image in the dimensions array
|
||||
* @param dimensions dimensions of resolution variants (sorted by size; smallest first)
|
||||
@@ -92,7 +92,7 @@ public class MultiResolutionImageSupport
|
||||
* for "disabled" state.
|
||||
*
|
||||
* @param image a multi-resolution image that is mapped using the given mapper function
|
||||
* @param mapper mapper function that maps a single resolution variant to a new image (e.g. applying an filter)
|
||||
* @param mapper mapper function that maps a single resolution variant to a new image (e.g. applying a filter)
|
||||
* @return a multi-resolution image on Java 9 or later; a mapped image on Java 8
|
||||
*/
|
||||
public static Image map( Image image, Function<Image, Image> mapper ) {
|
||||
@@ -104,7 +104,7 @@ public class MultiResolutionImageSupport
|
||||
* <p>
|
||||
* If the given image is a multi-resolution image then invokes
|
||||
* {@code java.awt.image.MultiResolutionImage.getResolutionVariant(destImageWidth, destImageHeight)}.
|
||||
* Otherwise returns the given image.
|
||||
* Otherwise, returns the given image.
|
||||
*/
|
||||
public static Image getResolutionVariant( Image image, int destImageWidth, int destImageHeight ) {
|
||||
return image;
|
||||
@@ -115,7 +115,7 @@ public class MultiResolutionImageSupport
|
||||
* <p>
|
||||
* If the given image is a multi-resolution image then invokes
|
||||
* {@code java.awt.image.MultiResolutionImage.getResolutionVariants()}.
|
||||
* Otherwise returns a list containing only the given image.
|
||||
* Otherwise, returns a list containing only the given image.
|
||||
*/
|
||||
public static List<Image> getResolutionVariants( Image image ) {
|
||||
return Collections.singletonList( image );
|
||||
|
||||
@@ -60,6 +60,19 @@ public class NativeLibrary
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load native library from given file.
|
||||
*
|
||||
* @param libraryFile the file of the native library
|
||||
* @param supported whether the native library is supported on the current platform
|
||||
* @since 2
|
||||
*/
|
||||
public NativeLibrary( File libraryFile, boolean supported ) {
|
||||
this.loaded = supported
|
||||
? loadLibraryFromFile( libraryFile )
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the native library is loaded.
|
||||
* <p>
|
||||
@@ -120,6 +133,16 @@ public class NativeLibrary
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadLibraryFromFile( File libraryFile ) {
|
||||
try {
|
||||
System.load( libraryFile.getAbsolutePath() );
|
||||
return true;
|
||||
} catch( Throwable ex ) {
|
||||
log( null, ex );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String decorateLibraryName( String libraryName ) {
|
||||
if( SystemInfo.isWindows )
|
||||
return libraryName.concat( ".dll" );
|
||||
@@ -172,7 +195,7 @@ public class NativeLibrary
|
||||
// for loaded native libraries, they will be deleted on next application startup.
|
||||
// The default temporary directory may contain hundreds or thousands of files.
|
||||
// To make searching for "marked for deletion" files as fast as possible,
|
||||
// use a sub directory that contains only our temporary native libraries.
|
||||
// use a subdirectory that contains only our temporary native libraries.
|
||||
tmpdir += "\\flatlaf.temp";
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
|
||||
/**
|
||||
* Utility methods for Swing.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public class SwingUtils
|
||||
{
|
||||
/**
|
||||
* Search for a (grand) child component with the given name.
|
||||
*
|
||||
* @return a component; or {@code null}
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public static <T extends Component> T getComponentByName( Container parent, String name ) {
|
||||
for( Component child : parent.getComponents() ) {
|
||||
if( name.equals( child.getName() ) )
|
||||
return (T) child;
|
||||
|
||||
if( child instanceof Container ) {
|
||||
T c = getComponentByName( (Container) child, name );
|
||||
if( c != null )
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,9 @@ public class SystemInfo
|
||||
// OS versions
|
||||
public static final long osVersion;
|
||||
public static final boolean isWindows_10_orLater;
|
||||
/** <strong>Note</strong>: This requires Java 8u321, 11.0.14, 17.0.2 or 18 (or later).
|
||||
* (see https://bugs.openjdk.java.net/browse/JDK-8274840)
|
||||
* @since 2 */ public static final boolean isWindows_11_orLater;
|
||||
public static final boolean isMacOS_10_11_ElCapitan_orLater;
|
||||
public static final boolean isMacOS_10_14_Mojave_orLater;
|
||||
public static final boolean isMacOS_10_15_Catalina_orLater;
|
||||
@@ -49,6 +52,7 @@ public class SystemInfo
|
||||
public static final boolean isJava_11_orLater;
|
||||
public static final boolean isJava_15_orLater;
|
||||
/** @since 2 */ public static final boolean isJava_17_orLater;
|
||||
/** @since 2 */ public static final boolean isJava_18_orLater;
|
||||
|
||||
// Java VMs
|
||||
public static final boolean isJetBrainsJVM;
|
||||
@@ -72,6 +76,8 @@ public class SystemInfo
|
||||
// OS versions
|
||||
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
||||
isWindows_10_orLater = (isWindows && osVersion >= toVersion( 10, 0, 0, 0 ));
|
||||
isWindows_11_orLater = (isWindows_10_orLater && osName.length() > "windows ".length() &&
|
||||
scanVersion( osName.substring( "windows ".length() ) ) >= toVersion( 11, 0, 0, 0 ));
|
||||
isMacOS_10_11_ElCapitan_orLater = (isMacOS && osVersion >= toVersion( 10, 11, 0, 0 ));
|
||||
isMacOS_10_14_Mojave_orLater = (isMacOS && osVersion >= toVersion( 10, 14, 0, 0 ));
|
||||
isMacOS_10_15_Catalina_orLater = (isMacOS && osVersion >= toVersion( 10, 15, 0, 0 ));
|
||||
@@ -88,6 +94,7 @@ public class SystemInfo
|
||||
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
|
||||
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
|
||||
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
|
||||
isJava_18_orLater = (javaVersion >= toVersion( 18, 0, 0, 0 ));
|
||||
|
||||
// Java VMs
|
||||
isJetBrainsJVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
||||
|
||||
@@ -103,7 +103,7 @@ public class UIScale
|
||||
// Java 9 and later supports per-monitor scaling
|
||||
jreHiDPI = true;
|
||||
} else if( SystemInfo.isJetBrainsJVM ) {
|
||||
// IntelliJ IDEA ships its own JetBrains Java 8 JRE that may supports per-monitor scaling
|
||||
// IntelliJ IDEA ships its own JetBrains Java 8 JRE that may support per-monitor scaling
|
||||
// see com.intellij.ui.JreHiDpiUtil.isJreHiDPIEnabled()
|
||||
try {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
@@ -411,7 +411,7 @@ public class UIScale
|
||||
* Scales the given dimension with the user scale factor.
|
||||
* <p>
|
||||
* If user scale factor is 1, then the given dimension is simply returned.
|
||||
* Otherwise a new instance of {@link Dimension} or {@link DimensionUIResource}
|
||||
* Otherwise, a new instance of {@link Dimension} or {@link DimensionUIResource}
|
||||
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
||||
*/
|
||||
public static Dimension scale( Dimension dimension ) {
|
||||
@@ -427,7 +427,7 @@ public class UIScale
|
||||
* Scales the given insets with the user scale factor.
|
||||
* <p>
|
||||
* If user scale factor is 1, then the given insets is simply returned.
|
||||
* Otherwise a new instance of {@link Insets} or {@link InsetsUIResource}
|
||||
* Otherwise, a new instance of {@link Insets} or {@link InsetsUIResource}
|
||||
* is returned, depending on whether the passed dimension implements {@link UIResource}.
|
||||
*/
|
||||
public static Insets scale( Insets insets ) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#
|
||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
# Instead, copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
# Instead, copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
# Colors and style mostly based on Darcula theme from IntelliJ IDEA Community Edition,
|
||||
@@ -240,6 +240,7 @@ MenuBar.borderColor = $Separator.foreground
|
||||
#---- PasswordField ----
|
||||
|
||||
PasswordField.capsLockIconColor = #ffffff64
|
||||
PasswordField.revealIconColor = @foreground
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
@@ -251,6 +252,7 @@ Popup.dropShadowOpacity = 0.25
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor = tint(@background,17%)
|
||||
PopupMenu.hoverScrollArrowBackground = lighten(@background,5%)
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
@@ -289,7 +291,7 @@ Slider.trackValueColor = @accentSliderColor
|
||||
Slider.trackColor = lighten(@background,15%)
|
||||
Slider.thumbColor = $Slider.trackValueColor
|
||||
Slider.tickColor = @disabledForeground
|
||||
Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
||||
Slider.focusedColor = fade(changeLightness($Component.focusColor,60%,derived),30%,derived)
|
||||
Slider.hoverThumbColor = lighten($Slider.thumbColor,5%,derived)
|
||||
Slider.pressedThumbColor = lighten($Slider.thumbColor,8%,derived)
|
||||
Slider.disabledTrackColor = lighten(@background,10%)
|
||||
@@ -334,8 +336,8 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||
#---- TitlePane ----
|
||||
|
||||
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,20%,derived)
|
||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,15%,derived)
|
||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,10%,derived)
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
@@ -367,7 +369,6 @@ Tree.hash = lighten($Tree.background,5%)
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: lighten($TextField.background,4%,derived); \
|
||||
toolbar.pressedBackground: lighten($TextField.background,6%,derived); \
|
||||
toolbar.selectedBackground: lighten($TextField.background,12%,derived)
|
||||
toolbar.hoverBackground: lighten($TextField.background,5%); \
|
||||
toolbar.pressedBackground: lighten($TextField.background,10%); \
|
||||
toolbar.selectedBackground: lighten($TextField.background,15%)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#
|
||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
# Instead, copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
# Instead, copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
#---- typography / fonts ----
|
||||
@@ -487,7 +487,6 @@ PasswordField.showCapsLock = true
|
||||
PasswordField.showRevealButton = false
|
||||
PasswordField.capsLockIcon = com.formdev.flatlaf.icons.FlatCapsLockIcon
|
||||
PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
||||
PasswordField.revealIconColor = lazy(Actions.Grey)
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
@@ -501,6 +500,7 @@ Popup.dropShadowInsets = -4,-4,4,4
|
||||
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
||||
PopupMenu.borderInsets = 4,1,4,1
|
||||
PopupMenu.background = @menuBackground
|
||||
PopupMenu.scrollArrowColor = @buttonArrowColor
|
||||
|
||||
|
||||
#---- PopupMenuSeparator ----
|
||||
@@ -555,6 +555,7 @@ RootPane.honorDialogMinimumSizeOnResize = true
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.width = 10
|
||||
ScrollBar.minimumButtonSize = 12,12
|
||||
ScrollBar.minimumThumbSize = 10,10
|
||||
ScrollBar.maximumThumbSize = 100000,100000
|
||||
ScrollBar.trackInsets = 0,0,0,0
|
||||
@@ -589,13 +590,13 @@ ScrollPane.smoothScrolling = true
|
||||
|
||||
#---- SearchField ----
|
||||
|
||||
SearchField.searchIconColor = fadeout(Actions.GreyInline,10%,lazy)
|
||||
SearchField.searchIconHoverColor = fadeout(Actions.GreyInline,30%,lazy)
|
||||
SearchField.searchIconPressedColor = fadeout(Actions.GreyInline,50%,lazy)
|
||||
SearchField.searchIconColor = fade(Actions.GreyInline,90%,lazy)
|
||||
SearchField.searchIconHoverColor = fade(Actions.GreyInline,70%,lazy)
|
||||
SearchField.searchIconPressedColor = fade(Actions.GreyInline,50%,lazy)
|
||||
|
||||
SearchField.clearIconColor = fadeout(Actions.GreyInline,50%,lazy)
|
||||
SearchField.clearIconColor = fade(Actions.GreyInline,50%,lazy)
|
||||
SearchField.clearIconHoverColor = $SearchField.clearIconColor
|
||||
SearchField.clearIconPressedColor = fadeout(Actions.GreyInline,20%,lazy)
|
||||
SearchField.clearIconPressedColor = fade(Actions.GreyInline,80%,lazy)
|
||||
|
||||
|
||||
#---- Separator ----
|
||||
@@ -802,8 +803,8 @@ TitlePane.inactiveBackground = $TitlePane.background
|
||||
TitlePane.foreground = @foreground
|
||||
TitlePane.inactiveForeground = @disabledForeground
|
||||
|
||||
TitlePane.closeHoverBackground = #e81123
|
||||
TitlePane.closePressedBackground = fade($TitlePane.closeHoverBackground,60%)
|
||||
TitlePane.closeHoverBackground = #c42b1c
|
||||
TitlePane.closePressedBackground = fade($TitlePane.closeHoverBackground,90%)
|
||||
TitlePane.closeHoverForeground = #fff
|
||||
TitlePane.closePressedForeground = #fff
|
||||
|
||||
@@ -920,6 +921,5 @@ Tree.icon.openColor = @icon
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: $TextField.background; \
|
||||
toolbar.pressedBackground: $TextField.background
|
||||
toolbar.hoverBackground: null; \
|
||||
toolbar.pressedBackground: null
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# NOTE: Avoid copying the whole content of this file to own properties files.
|
||||
# This will make upgrading to newer FlatLaf versions complex and error-prone.
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
# Instead, copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
# Colors and style mostly based on IntelliJ theme from IntelliJ IDEA Community Edition,
|
||||
@@ -247,6 +247,7 @@ MenuBar.borderColor = $Separator.foreground
|
||||
#---- PasswordField ----
|
||||
|
||||
PasswordField.capsLockIconColor = #00000064
|
||||
PasswordField.revealIconColor = tint(@foreground,40%)
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
@@ -258,6 +259,7 @@ Popup.dropShadowOpacity = 0.15
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor = shade(@background,28%)
|
||||
PopupMenu.hoverScrollArrowBackground = darken(@background,5%)
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
@@ -296,7 +298,7 @@ Slider.trackValueColor = @accentSliderColor
|
||||
Slider.trackColor = darken(@background,18%)
|
||||
Slider.thumbColor = $Slider.trackValueColor
|
||||
Slider.tickColor = @disabledForeground
|
||||
Slider.focusedColor = fade($Component.focusColor,50%,derived)
|
||||
Slider.focusedColor = fade(changeLightness($Component.focusColor,75%,derived),50%,derived)
|
||||
Slider.hoverThumbColor = darken($Slider.thumbColor,5%,derived)
|
||||
Slider.pressedThumbColor = darken($Slider.thumbColor,8%,derived)
|
||||
Slider.disabledTrackColor = darken(@background,13%)
|
||||
@@ -342,7 +344,7 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||
|
||||
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
||||
TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,20%,derived)
|
||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,8%,derived)
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
@@ -374,7 +376,6 @@ Tree.hash = darken($Tree.background,10%)
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: darken($TextField.background,4%,derived); \
|
||||
toolbar.pressedBackground: darken($TextField.background,8%,derived); \
|
||||
toolbar.selectedBackground: darken($TextField.background,12%,derived)
|
||||
toolbar.hoverBackground: darken($TextField.background,4%); \
|
||||
toolbar.pressedBackground: darken($TextField.background,8%); \
|
||||
toolbar.selectedBackground: darken($TextField.background,12%)
|
||||
|
||||
@@ -91,33 +91,33 @@ ToggleButton.endBackground = $ToggleButton.background
|
||||
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
|
||||
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
|
||||
|
||||
[Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme]ProgressBar.selectionBackground = #000
|
||||
[Arc_Theme]ProgressBar.selectionForeground = #fff
|
||||
[Arc_Theme]List.selectionInactiveForeground = #fff
|
||||
[Arc_Theme]Table.selectionInactiveForeground = #fff
|
||||
[Arc_Theme]Tree.selectionInactiveForeground = #fff
|
||||
|
||||
[Arc_Theme_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_-_Orange]ProgressBar.selectionBackground = #000
|
||||
[Arc_Theme_-_Orange]ProgressBar.selectionForeground = #fff
|
||||
[Arc_Theme_-_Orange]List.selectionInactiveForeground = #fff
|
||||
[Arc_Theme_-_Orange]Table.selectionInactiveForeground = #fff
|
||||
[Arc_Theme_-_Orange]Tree.selectionInactiveForeground = #fff
|
||||
|
||||
[Arc_Theme_Dark]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark]ProgressBar.selectionBackground = #ddd
|
||||
[Arc_Theme_Dark]ProgressBar.selectionForeground = #ddd
|
||||
|
||||
[Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
|
||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionBackground = #ddd
|
||||
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionForeground = #fff
|
||||
|
||||
@@ -152,13 +152,17 @@ ToggleButton.endBackground = $ToggleButton.background
|
||||
|
||||
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[High_contrast]ToggleButton.selectedBackground = #fff
|
||||
[High_contrast]ToggleButton.selectedForeground = #000
|
||||
[High_contrast]ToggleButton.disabledSelectedBackground = #444
|
||||
[High_contrast]ToggleButton.toolbar.selectedBackground = #fff
|
||||
[High_contrast][style]Button.inTextField = \
|
||||
toolbar.hoverBackground: #444; \
|
||||
toolbar.pressedBackground: #666; \
|
||||
toolbar.selectedBackground: #fff
|
||||
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
|
||||
|
||||
[Light_Flat]TableHeader.background = #E5E5E9
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2022 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.Icon;
|
||||
import com.formdev.flatlaf.ui.TestUtils;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
class TestFlatIconPaintingNullComponent
|
||||
{
|
||||
static Graphics graphics;
|
||||
|
||||
@BeforeAll
|
||||
static void setup() {
|
||||
TestUtils.setup( false );
|
||||
graphics = new BufferedImage( 32, 32, BufferedImage.TYPE_INT_ARGB ).getGraphics();
|
||||
graphics.setColor( Color.white );
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void cleanup() {
|
||||
TestUtils.cleanup();
|
||||
graphics = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void flatHelpButtonIcon() {
|
||||
paintWithoutException( new FlatHelpButtonIcon() );
|
||||
}
|
||||
|
||||
@Test
|
||||
void flatMenuArrowIcon() {
|
||||
paintWithoutException( new FlatMenuArrowIcon() );
|
||||
}
|
||||
|
||||
@Test
|
||||
void flatSearchIcon() {
|
||||
paintWithoutException( new FlatSearchIcon() );
|
||||
}
|
||||
|
||||
private void paintWithoutException( Icon icon ) {
|
||||
graphics.clearRect( 0, 0, 32, 32 );
|
||||
assertDoesNotThrow( () -> icon.paintIcon( null, graphics, 0, 0 ) );
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class TestFlatStyleClasses
|
||||
|
||||
@BeforeAll
|
||||
static void setup() {
|
||||
System.setProperty( FlatSystemProperties.UI_SCALE_ENABLED, "false" );
|
||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||
TestUtils.setup( false );
|
||||
|
||||
UIManager.put( "[style]Button.primary", BUTTON_PRIMARY );
|
||||
@@ -100,7 +100,7 @@ public class TestFlatStyleClasses
|
||||
@AfterAll
|
||||
static void cleanup() {
|
||||
TestUtils.cleanup();
|
||||
System.clearProperty( FlatSystemProperties.UI_SCALE_ENABLED );
|
||||
System.clearProperty( FlatSystemProperties.UI_SCALE );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -422,6 +422,10 @@ public class TestFlatStyleableInfo
|
||||
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
||||
|
||||
Map<String, Class<?>> expected = expectedMap(
|
||||
"arrowType", String.class,
|
||||
"scrollArrowColor", Color.class,
|
||||
"hoverScrollArrowBackground", Color.class,
|
||||
|
||||
"borderInsets", Insets.class,
|
||||
"borderColor", Color.class
|
||||
);
|
||||
@@ -539,6 +543,7 @@ public class TestFlatStyleableInfo
|
||||
"maximumThumbSize", Dimension.class,
|
||||
"allowsAbsolutePositioning", boolean.class,
|
||||
|
||||
"minimumButtonSize", Dimension.class,
|
||||
"trackInsets", Insets.class,
|
||||
"thumbInsets", Insets.class,
|
||||
"trackArc", int.class,
|
||||
|
||||
@@ -565,6 +565,10 @@ public class TestFlatStyling
|
||||
JPopupMenu c = new JPopupMenu();
|
||||
FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI();
|
||||
|
||||
ui.applyStyle( "arrowType: chevron" );
|
||||
ui.applyStyle( "scrollArrowColor: #fff" );
|
||||
ui.applyStyle( "hoverScrollArrowBackground: #fff" );
|
||||
|
||||
ui.applyStyle( "borderInsets: 1,2,3,4" );
|
||||
ui.applyStyle( "borderColor: #fff" );
|
||||
|
||||
@@ -684,6 +688,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "maximumThumbSize: 1,2" );
|
||||
ui.applyStyle( "allowsAbsolutePositioning: true" );
|
||||
|
||||
ui.applyStyle( "minimumButtonSize: 1,2" );
|
||||
ui.applyStyle( "trackInsets: 1,2,3,4" );
|
||||
ui.applyStyle( "thumbInsets: 1,2,3,4" );
|
||||
ui.applyStyle( "trackArc: 5" );
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
||||
*/
|
||||
public class TestUtils
|
||||
{
|
||||
public static final float[] FACTORS = new float[] { 1f }; //, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||
public static final float[] FACTORS = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||
|
||||
public static void setup( boolean withFocus ) {
|
||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||
|
||||
@@ -43,6 +43,17 @@ class BasicComponentsPanel
|
||||
// UIManager.put( "PasswordField.showRevealButton", true );
|
||||
passwordField1.putClientProperty( FlatClientProperties.STYLE, "showRevealButton: true" );
|
||||
|
||||
// add leading/trailing icons to text fields
|
||||
leadingIconTextField.putClientProperty( FlatClientProperties.PLACEHOLDER_TEXT, "Search" );
|
||||
leadingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||
new FlatSearchIcon() );
|
||||
trailingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/DataTables.svg" ) );
|
||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/user.svg" ) );
|
||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/bookmarkGroup.svg" ) );
|
||||
|
||||
// search history button
|
||||
JButton searchHistoryButton = new JButton( new FlatSearchWithHistoryIcon( true ) );
|
||||
searchHistoryButton.setToolTipText( "Search History" );
|
||||
@@ -177,9 +188,9 @@ class BasicComponentsPanel
|
||||
JComboBox<String> warningHintsComboBox = new JComboBox<>();
|
||||
JSpinner warningHintsSpinner = new JSpinner();
|
||||
JLabel iconsLabel = new JLabel();
|
||||
JTextField leadingIconTextField = new JTextField();
|
||||
JTextField trailingIconTextField = new JTextField();
|
||||
JTextField iconsTextField = new JTextField();
|
||||
leadingIconTextField = new JTextField();
|
||||
trailingIconTextField = new JTextField();
|
||||
iconsTextField = new JTextField();
|
||||
JLabel compsLabel = new JLabel();
|
||||
compsTextField = new JTextField();
|
||||
clearTextField = new JTextField();
|
||||
@@ -851,17 +862,6 @@ class BasicComponentsPanel
|
||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
|
||||
// add leading/trailing icons to text fields
|
||||
leadingIconTextField.putClientProperty( FlatClientProperties.PLACEHOLDER_TEXT, "Search" );
|
||||
leadingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||
new FlatSearchIcon() );
|
||||
trailingIconTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/DataTables.svg" ) );
|
||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/user.svg" ) );
|
||||
iconsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON,
|
||||
new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/bookmarkGroup.svg" ) );
|
||||
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
// hide some components
|
||||
Component[] hiddenComponents = {
|
||||
@@ -919,6 +919,9 @@ class BasicComponentsPanel
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JPasswordField passwordField1;
|
||||
private JTextField leadingIconTextField;
|
||||
private JTextField trailingIconTextField;
|
||||
private JTextField iconsTextField;
|
||||
private JTextField compsTextField;
|
||||
private JTextField clearTextField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
@@ -659,18 +659,27 @@ new FormModel {
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "leadingIconTextField"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 14,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "trailingIconTextField"
|
||||
"text": "text"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 14,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "iconsTextField"
|
||||
"text": "text"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 14,growx"
|
||||
} )
|
||||
|
||||
@@ -62,10 +62,10 @@ class ControlBar
|
||||
|
||||
// initialize look and feels combo box
|
||||
DefaultComboBoxModel<LookAndFeelInfo> lafModel = new DefaultComboBoxModel<>();
|
||||
lafModel.addElement( new LookAndFeelInfo( "Flat Light (F1)", FlatLightLaf.class.getName() ) );
|
||||
lafModel.addElement( new LookAndFeelInfo( "Flat Dark (F2)", FlatDarkLaf.class.getName() ) );
|
||||
lafModel.addElement( new LookAndFeelInfo( "Flat IntelliJ (F3)", FlatIntelliJLaf.class.getName() ) );
|
||||
lafModel.addElement( new LookAndFeelInfo( "Flat Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
||||
lafModel.addElement( new LookAndFeelInfo( "FlatLaf Light (F1)", FlatLightLaf.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 Darcula (F4)", FlatDarculaLaf.class.getName() ) );
|
||||
|
||||
UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
|
||||
for( UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels ) {
|
||||
|
||||
@@ -464,6 +464,7 @@ class DemoFrame
|
||||
JMenuItem projectViewMenuItem = new JMenuItem();
|
||||
JMenuItem structureViewMenuItem = new JMenuItem();
|
||||
JMenuItem propertiesViewMenuItem = new JMenuItem();
|
||||
scrollingPopupMenu = new JMenu();
|
||||
JMenuItem menuItem2 = new JMenuItem();
|
||||
htmlMenuItem = new JMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
|
||||
@@ -668,6 +669,12 @@ class DemoFrame
|
||||
}
|
||||
viewMenu.add(menu1);
|
||||
|
||||
//======== scrollingPopupMenu ========
|
||||
{
|
||||
scrollingPopupMenu.setText("Scrolling Popup Menu");
|
||||
}
|
||||
viewMenu.add(scrollingPopupMenu);
|
||||
|
||||
//---- menuItem2 ----
|
||||
menuItem2.setText("Disabled Item");
|
||||
menuItem2.setEnabled(false);
|
||||
@@ -889,8 +896,17 @@ class DemoFrame
|
||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
||||
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
||||
scrollingPopupMenu.add( "Large menus are scrollable" );
|
||||
scrollingPopupMenu.add( "Use mouse wheel to scroll" );
|
||||
scrollingPopupMenu.add( "Or use up/down arrows at top/bottom" );
|
||||
for( int i = 1; i <= 100; i++ )
|
||||
scrollingPopupMenu.add( "Item " + i );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() || (SystemInfo.isLinux && JFrame.isDefaultLookAndFeelDecorated()) ) {
|
||||
if( SystemInfo.isLinux )
|
||||
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||
else
|
||||
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
||||
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
|
||||
@@ -931,6 +947,7 @@ class DemoFrame
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JMenuItem exitMenuItem;
|
||||
private JMenu scrollingPopupMenu;
|
||||
private JMenuItem htmlMenuItem;
|
||||
private JMenu fontMenu;
|
||||
private JMenu optionsMenu;
|
||||
|
||||
@@ -282,6 +282,13 @@ new FormModel {
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "scrollingPopupMenu"
|
||||
"text": "Scrolling Popup Menu"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem2"
|
||||
"text": "Disabled Item"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.formdev.flatlaf.demo;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.extras.FlatInspector;
|
||||
@@ -52,6 +54,13 @@ public class FlatLafDemo
|
||||
System.setProperty( "apple.awt.application.appearance", "system" );
|
||||
}
|
||||
|
||||
// Linux
|
||||
if( SystemInfo.isLinux ) {
|
||||
// enable custom window decorations
|
||||
JFrame.setDefaultLookAndFeelDecorated( true );
|
||||
JDialog.setDefaultLookAndFeelDecorated( true );
|
||||
}
|
||||
|
||||
if( FlatLafDemo.screenshotsMode && !SystemInfo.isJava_9_orLater && System.getProperty( "flatlaf.uiScale" ) == null )
|
||||
System.setProperty( "flatlaf.uiScale", "2x" );
|
||||
|
||||
|
||||
@@ -412,7 +412,6 @@ class TabsPanel
|
||||
cardTabTypeButton = new JToggleButton();
|
||||
|
||||
//======== this ========
|
||||
setName("this");
|
||||
setLayout(new MigLayout(
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
@@ -426,7 +425,6 @@ class TabsPanel
|
||||
|
||||
//======== panel1 ========
|
||||
{
|
||||
panel1.setName("panel1");
|
||||
panel1.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
@@ -445,41 +443,35 @@ class TabsPanel
|
||||
//---- tabPlacementLabel ----
|
||||
tabPlacementLabel.setText("Tab placement");
|
||||
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabPlacementLabel.setName("tabPlacementLabel");
|
||||
panel1.add(tabPlacementLabel, "cell 0 0");
|
||||
|
||||
//======== tabPlacementToolBar ========
|
||||
{
|
||||
tabPlacementToolBar.setFloatable(false);
|
||||
tabPlacementToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
tabPlacementToolBar.setName("tabPlacementToolBar");
|
||||
|
||||
//---- topPlacementButton ----
|
||||
topPlacementButton.setText("top");
|
||||
topPlacementButton.setSelected(true);
|
||||
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
topPlacementButton.setName("topPlacementButton");
|
||||
topPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(topPlacementButton);
|
||||
|
||||
//---- bottomPlacementButton ----
|
||||
bottomPlacementButton.setText("bottom");
|
||||
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
bottomPlacementButton.setName("bottomPlacementButton");
|
||||
bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(bottomPlacementButton);
|
||||
|
||||
//---- leftPlacementButton ----
|
||||
leftPlacementButton.setText("left");
|
||||
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leftPlacementButton.setName("leftPlacementButton");
|
||||
leftPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(leftPlacementButton);
|
||||
|
||||
//---- rightPlacementButton ----
|
||||
rightPlacementButton.setText("right");
|
||||
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
rightPlacementButton.setName("rightPlacementButton");
|
||||
rightPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(rightPlacementButton);
|
||||
tabPlacementToolBar.addSeparator();
|
||||
@@ -487,49 +479,38 @@ class TabsPanel
|
||||
//---- scrollButton ----
|
||||
scrollButton.setText("scroll");
|
||||
scrollButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollButton.setName("scrollButton");
|
||||
scrollButton.addActionListener(e -> scrollChanged());
|
||||
tabPlacementToolBar.add(scrollButton);
|
||||
|
||||
//---- borderButton ----
|
||||
borderButton.setText("border");
|
||||
borderButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
borderButton.setName("borderButton");
|
||||
borderButton.addActionListener(e -> borderChanged());
|
||||
tabPlacementToolBar.add(borderButton);
|
||||
}
|
||||
panel1.add(tabPlacementToolBar, "cell 0 0,alignx right,growx 0");
|
||||
|
||||
//======== tabPlacementTabbedPane ========
|
||||
{
|
||||
tabPlacementTabbedPane.setName("tabPlacementTabbedPane");
|
||||
}
|
||||
panel1.add(tabPlacementTabbedPane, "cell 0 1,width 300:300,height 100:100");
|
||||
|
||||
//---- tabLayoutLabel ----
|
||||
tabLayoutLabel.setText("Tab layout");
|
||||
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabLayoutLabel.setName("tabLayoutLabel");
|
||||
panel1.add(tabLayoutLabel, "cell 0 2");
|
||||
|
||||
//======== tabLayoutToolBar ========
|
||||
{
|
||||
tabLayoutToolBar.setFloatable(false);
|
||||
tabLayoutToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
tabLayoutToolBar.setName("tabLayoutToolBar");
|
||||
|
||||
//---- scrollTabLayoutButton ----
|
||||
scrollTabLayoutButton.setText("scroll");
|
||||
scrollTabLayoutButton.setSelected(true);
|
||||
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTabLayoutButton.setName("scrollTabLayoutButton");
|
||||
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(scrollTabLayoutButton);
|
||||
|
||||
//---- wrapTabLayoutButton ----
|
||||
wrapTabLayoutButton.setText("wrap");
|
||||
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapTabLayoutButton.setName("wrapTabLayoutButton");
|
||||
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(wrapTabLayoutButton);
|
||||
}
|
||||
@@ -539,87 +520,62 @@ class TabsPanel
|
||||
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
|
||||
scrollLayoutNoteLabel.setEnabled(false);
|
||||
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollLayoutNoteLabel.setName("scrollLayoutNoteLabel");
|
||||
panel1.add(scrollLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
//---- wrapLayoutNoteLabel ----
|
||||
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
|
||||
wrapLayoutNoteLabel.setEnabled(false);
|
||||
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapLayoutNoteLabel.setName("wrapLayoutNoteLabel");
|
||||
panel1.add(wrapLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
//======== scrollLayoutTabbedPane ========
|
||||
{
|
||||
scrollLayoutTabbedPane.setName("scrollLayoutTabbedPane");
|
||||
}
|
||||
panel1.add(scrollLayoutTabbedPane, "cell 0 4");
|
||||
|
||||
//======== wrapLayoutTabbedPane ========
|
||||
{
|
||||
wrapLayoutTabbedPane.setName("wrapLayoutTabbedPane");
|
||||
}
|
||||
panel1.add(wrapLayoutTabbedPane, "cell 0 4,width 100:100,height pref*2px");
|
||||
|
||||
//---- closableTabsLabel ----
|
||||
closableTabsLabel.setText("Closable tabs");
|
||||
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
closableTabsLabel.setName("closableTabsLabel");
|
||||
panel1.add(closableTabsLabel, "cell 0 5");
|
||||
|
||||
//======== closableTabsToolBar ========
|
||||
{
|
||||
closableTabsToolBar.setFloatable(false);
|
||||
closableTabsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
closableTabsToolBar.setName("closableTabsToolBar");
|
||||
|
||||
//---- squareCloseButton ----
|
||||
squareCloseButton.setText("square");
|
||||
squareCloseButton.setSelected(true);
|
||||
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
squareCloseButton.setName("squareCloseButton");
|
||||
squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(squareCloseButton);
|
||||
|
||||
//---- circleCloseButton ----
|
||||
circleCloseButton.setText("circle");
|
||||
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
circleCloseButton.setName("circleCloseButton");
|
||||
circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(circleCloseButton);
|
||||
|
||||
//---- redCrossCloseButton ----
|
||||
redCrossCloseButton.setText("red cross");
|
||||
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
redCrossCloseButton.setName("redCrossCloseButton");
|
||||
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(redCrossCloseButton);
|
||||
}
|
||||
panel1.add(closableTabsToolBar, "cell 0 5,alignx right,growx 0");
|
||||
|
||||
//======== closableTabsTabbedPane ========
|
||||
{
|
||||
closableTabsTabbedPane.setName("closableTabsTabbedPane");
|
||||
}
|
||||
panel1.add(closableTabsTabbedPane, "cell 0 6");
|
||||
|
||||
//---- tabAreaComponentsLabel ----
|
||||
tabAreaComponentsLabel.setText("Custom tab area components");
|
||||
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaComponentsLabel.setName("tabAreaComponentsLabel");
|
||||
panel1.add(tabAreaComponentsLabel, "cell 0 7");
|
||||
|
||||
//======== tabAreaComponentsToolBar ========
|
||||
{
|
||||
tabAreaComponentsToolBar.setFloatable(false);
|
||||
tabAreaComponentsToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
tabAreaComponentsToolBar.setName("tabAreaComponentsToolBar");
|
||||
|
||||
//---- leadingComponentButton ----
|
||||
leadingComponentButton.setText("leading");
|
||||
leadingComponentButton.setSelected(true);
|
||||
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leadingComponentButton.setName("leadingComponentButton");
|
||||
leadingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(leadingComponentButton);
|
||||
|
||||
@@ -627,23 +583,16 @@ class TabsPanel
|
||||
trailingComponentButton.setText("trailing");
|
||||
trailingComponentButton.setSelected(true);
|
||||
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
trailingComponentButton.setName("trailingComponentButton");
|
||||
trailingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(trailingComponentButton);
|
||||
}
|
||||
panel1.add(tabAreaComponentsToolBar, "cell 0 7,alignx right,growx 0");
|
||||
|
||||
//======== customComponentsTabbedPane ========
|
||||
{
|
||||
customComponentsTabbedPane.setName("customComponentsTabbedPane");
|
||||
}
|
||||
panel1.add(customComponentsTabbedPane, "cell 0 8");
|
||||
}
|
||||
add(panel1, "cell 0 0");
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setName("panel2");
|
||||
panel2.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
@@ -665,82 +614,37 @@ class TabsPanel
|
||||
//---- tabIconPlacementLabel ----
|
||||
tabIconPlacementLabel.setText("Tab icon placement");
|
||||
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabIconPlacementLabel.setName("tabIconPlacementLabel");
|
||||
panel2.add(tabIconPlacementLabel, "cell 0 0");
|
||||
|
||||
//---- tabIconPlacementNodeLabel ----
|
||||
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
|
||||
tabIconPlacementNodeLabel.setEnabled(false);
|
||||
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabIconPlacementNodeLabel.setName("tabIconPlacementNodeLabel");
|
||||
panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
|
||||
|
||||
//======== iconTopTabbedPane ========
|
||||
{
|
||||
iconTopTabbedPane.setName("iconTopTabbedPane");
|
||||
}
|
||||
panel2.add(iconTopTabbedPane, "cell 0 2");
|
||||
|
||||
//======== iconBottomTabbedPane ========
|
||||
{
|
||||
iconBottomTabbedPane.setName("iconBottomTabbedPane");
|
||||
}
|
||||
panel2.add(iconBottomTabbedPane, "cell 0 3");
|
||||
|
||||
//======== iconLeadingTabbedPane ========
|
||||
{
|
||||
iconLeadingTabbedPane.setName("iconLeadingTabbedPane");
|
||||
}
|
||||
panel2.add(iconLeadingTabbedPane, "cell 0 4");
|
||||
|
||||
//======== iconTrailingTabbedPane ========
|
||||
{
|
||||
iconTrailingTabbedPane.setName("iconTrailingTabbedPane");
|
||||
}
|
||||
panel2.add(iconTrailingTabbedPane, "cell 0 5");
|
||||
|
||||
//---- tabAreaAlignmentLabel ----
|
||||
tabAreaAlignmentLabel.setText("Tab area alignment");
|
||||
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaAlignmentLabel.setName("tabAreaAlignmentLabel");
|
||||
panel2.add(tabAreaAlignmentLabel, "cell 0 6");
|
||||
|
||||
//---- tabAreaAlignmentNoteLabel ----
|
||||
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
|
||||
tabAreaAlignmentNoteLabel.setEnabled(false);
|
||||
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAreaAlignmentNoteLabel.setName("tabAreaAlignmentNoteLabel");
|
||||
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
|
||||
|
||||
//======== alignLeadingTabbedPane ========
|
||||
{
|
||||
alignLeadingTabbedPane.setName("alignLeadingTabbedPane");
|
||||
}
|
||||
panel2.add(alignLeadingTabbedPane, "cell 0 8");
|
||||
|
||||
//======== alignCenterTabbedPane ========
|
||||
{
|
||||
alignCenterTabbedPane.setName("alignCenterTabbedPane");
|
||||
}
|
||||
panel2.add(alignCenterTabbedPane, "cell 0 9");
|
||||
|
||||
//======== alignTrailingTabbedPane ========
|
||||
{
|
||||
alignTrailingTabbedPane.setName("alignTrailingTabbedPane");
|
||||
}
|
||||
panel2.add(alignTrailingTabbedPane, "cell 0 10");
|
||||
|
||||
//======== alignFillTabbedPane ========
|
||||
{
|
||||
alignFillTabbedPane.setName("alignFillTabbedPane");
|
||||
}
|
||||
panel2.add(alignFillTabbedPane, "cell 0 11");
|
||||
}
|
||||
add(panel2, "cell 1 0,growy");
|
||||
|
||||
//======== panel3 ========
|
||||
{
|
||||
panel3.setName("panel3");
|
||||
panel3.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
@@ -760,61 +664,31 @@ class TabsPanel
|
||||
//---- tabWidthModeLabel ----
|
||||
tabWidthModeLabel.setText("Tab width mode");
|
||||
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabWidthModeLabel.setName("tabWidthModeLabel");
|
||||
panel3.add(tabWidthModeLabel, "cell 0 0");
|
||||
|
||||
//---- tabWidthModeNoteLabel ----
|
||||
tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
|
||||
tabWidthModeNoteLabel.setEnabled(false);
|
||||
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabWidthModeNoteLabel.setName("tabWidthModeNoteLabel");
|
||||
panel3.add(tabWidthModeNoteLabel, "cell 0 1");
|
||||
|
||||
//======== widthPreferredTabbedPane ========
|
||||
{
|
||||
widthPreferredTabbedPane.setName("widthPreferredTabbedPane");
|
||||
}
|
||||
panel3.add(widthPreferredTabbedPane, "cell 0 2");
|
||||
|
||||
//======== widthEqualTabbedPane ========
|
||||
{
|
||||
widthEqualTabbedPane.setName("widthEqualTabbedPane");
|
||||
}
|
||||
panel3.add(widthEqualTabbedPane, "cell 0 3");
|
||||
|
||||
//======== widthCompactTabbedPane ========
|
||||
{
|
||||
widthCompactTabbedPane.setName("widthCompactTabbedPane");
|
||||
}
|
||||
panel3.add(widthCompactTabbedPane, "cell 0 4");
|
||||
|
||||
//---- minMaxTabWidthLabel ----
|
||||
minMaxTabWidthLabel.setText("Minimum/maximum tab width");
|
||||
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
minMaxTabWidthLabel.setName("minMaxTabWidthLabel");
|
||||
panel3.add(minMaxTabWidthLabel, "cell 0 5");
|
||||
|
||||
//======== minimumTabWidthTabbedPane ========
|
||||
{
|
||||
minimumTabWidthTabbedPane.setName("minimumTabWidthTabbedPane");
|
||||
}
|
||||
panel3.add(minimumTabWidthTabbedPane, "cell 0 6");
|
||||
|
||||
//======== maximumTabWidthTabbedPane ========
|
||||
{
|
||||
maximumTabWidthTabbedPane.setName("maximumTabWidthTabbedPane");
|
||||
}
|
||||
panel3.add(maximumTabWidthTabbedPane, "cell 0 7");
|
||||
|
||||
//---- tabAlignmentLabel ----
|
||||
tabAlignmentLabel.setText("Tab title alignment");
|
||||
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAlignmentLabel.setName("tabAlignmentLabel");
|
||||
panel3.add(tabAlignmentLabel, "cell 0 8");
|
||||
|
||||
//======== panel5 ========
|
||||
{
|
||||
panel5.setName("panel5");
|
||||
panel5.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
@@ -830,52 +704,30 @@ class TabsPanel
|
||||
tabAlignmentNoteLabel.setText("(leading/center/trailing)");
|
||||
tabAlignmentNoteLabel.setEnabled(false);
|
||||
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel.setName("tabAlignmentNoteLabel");
|
||||
panel5.add(tabAlignmentNoteLabel, "cell 0 0");
|
||||
|
||||
//---- tabAlignmentNoteLabel2 ----
|
||||
tabAlignmentNoteLabel2.setText("(trailing)");
|
||||
tabAlignmentNoteLabel2.setEnabled(false);
|
||||
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel2.setName("tabAlignmentNoteLabel2");
|
||||
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
|
||||
|
||||
//======== tabAlignLeadingTabbedPane ========
|
||||
{
|
||||
tabAlignLeadingTabbedPane.setName("tabAlignLeadingTabbedPane");
|
||||
}
|
||||
panel5.add(tabAlignLeadingTabbedPane, "cell 0 1");
|
||||
|
||||
//======== tabAlignVerticalTabbedPane ========
|
||||
{
|
||||
tabAlignVerticalTabbedPane.setTabPlacement(SwingConstants.LEFT);
|
||||
tabAlignVerticalTabbedPane.setName("tabAlignVerticalTabbedPane");
|
||||
}
|
||||
panel5.add(tabAlignVerticalTabbedPane, "cell 1 1 1 3,growy");
|
||||
|
||||
//======== tabAlignCenterTabbedPane ========
|
||||
{
|
||||
tabAlignCenterTabbedPane.setName("tabAlignCenterTabbedPane");
|
||||
}
|
||||
panel5.add(tabAlignCenterTabbedPane, "cell 0 2");
|
||||
|
||||
//======== tabAlignTrailingTabbedPane ========
|
||||
{
|
||||
tabAlignTrailingTabbedPane.setName("tabAlignTrailingTabbedPane");
|
||||
}
|
||||
panel5.add(tabAlignTrailingTabbedPane, "cell 0 3");
|
||||
}
|
||||
panel3.add(panel5, "cell 0 9");
|
||||
}
|
||||
add(panel3, "cell 2 0");
|
||||
|
||||
//---- separator2 ----
|
||||
separator2.setName("separator2");
|
||||
add(separator2, "cell 0 1 3 1");
|
||||
|
||||
//======== panel4 ========
|
||||
{
|
||||
panel4.setName("panel4");
|
||||
panel4.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
@@ -890,34 +742,29 @@ class TabsPanel
|
||||
|
||||
//---- scrollButtonsPolicyLabel ----
|
||||
scrollButtonsPolicyLabel.setText("Scroll buttons policy:");
|
||||
scrollButtonsPolicyLabel.setName("scrollButtonsPolicyLabel");
|
||||
panel4.add(scrollButtonsPolicyLabel, "cell 0 0");
|
||||
|
||||
//======== scrollButtonsPolicyToolBar ========
|
||||
{
|
||||
scrollButtonsPolicyToolBar.setFloatable(false);
|
||||
scrollButtonsPolicyToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
scrollButtonsPolicyToolBar.setName("scrollButtonsPolicyToolBar");
|
||||
|
||||
//---- scrollAsNeededSingleButton ----
|
||||
scrollAsNeededSingleButton.setText("asNeededSingle");
|
||||
scrollAsNeededSingleButton.setSelected(true);
|
||||
scrollAsNeededSingleButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededSingleButton.setName("scrollAsNeededSingleButton");
|
||||
scrollAsNeededSingleButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededSingleButton);
|
||||
|
||||
//---- scrollAsNeededButton ----
|
||||
scrollAsNeededButton.setText("asNeeded");
|
||||
scrollAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededButton.setName("scrollAsNeededButton");
|
||||
scrollAsNeededButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededButton);
|
||||
|
||||
//---- scrollNeverButton ----
|
||||
scrollNeverButton.setText("never");
|
||||
scrollNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollNeverButton.setName("scrollNeverButton");
|
||||
scrollNeverButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollNeverButton);
|
||||
}
|
||||
@@ -925,27 +772,23 @@ class TabsPanel
|
||||
|
||||
//---- scrollButtonsPlacementLabel ----
|
||||
scrollButtonsPlacementLabel.setText("Scroll buttons placement:");
|
||||
scrollButtonsPlacementLabel.setName("scrollButtonsPlacementLabel");
|
||||
panel4.add(scrollButtonsPlacementLabel, "cell 2 0");
|
||||
|
||||
//======== scrollButtonsPlacementToolBar ========
|
||||
{
|
||||
scrollButtonsPlacementToolBar.setFloatable(false);
|
||||
scrollButtonsPlacementToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
scrollButtonsPlacementToolBar.setName("scrollButtonsPlacementToolBar");
|
||||
|
||||
//---- scrollBothButton ----
|
||||
scrollBothButton.setText("both");
|
||||
scrollBothButton.setSelected(true);
|
||||
scrollBothButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollBothButton.setName("scrollBothButton");
|
||||
scrollBothButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollBothButton);
|
||||
|
||||
//---- scrollTrailingButton ----
|
||||
scrollTrailingButton.setText("trailing");
|
||||
scrollTrailingButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTrailingButton.setName("scrollTrailingButton");
|
||||
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollTrailingButton);
|
||||
}
|
||||
@@ -953,33 +796,28 @@ class TabsPanel
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.setName("showTabSeparatorsCheckBox");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
panel4.add(showTabSeparatorsCheckBox, "cell 4 0");
|
||||
|
||||
//---- tabsPopupPolicyLabel ----
|
||||
tabsPopupPolicyLabel.setText("Tabs popup policy:");
|
||||
tabsPopupPolicyLabel.setName("tabsPopupPolicyLabel");
|
||||
panel4.add(tabsPopupPolicyLabel, "cell 0 1");
|
||||
|
||||
//======== tabsPopupPolicyToolBar ========
|
||||
{
|
||||
tabsPopupPolicyToolBar.setFloatable(false);
|
||||
tabsPopupPolicyToolBar.setBorder(BorderFactory.createEmptyBorder());
|
||||
tabsPopupPolicyToolBar.setName("tabsPopupPolicyToolBar");
|
||||
|
||||
//---- popupAsNeededButton ----
|
||||
popupAsNeededButton.setText("asNeeded");
|
||||
popupAsNeededButton.setSelected(true);
|
||||
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupAsNeededButton.setName("popupAsNeededButton");
|
||||
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupAsNeededButton);
|
||||
|
||||
//---- popupNeverButton ----
|
||||
popupNeverButton.setText("never");
|
||||
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupNeverButton.setName("popupNeverButton");
|
||||
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupNeverButton);
|
||||
}
|
||||
@@ -987,26 +825,22 @@ class TabsPanel
|
||||
|
||||
//---- tabTypeLabel ----
|
||||
tabTypeLabel.setText("Tab type:");
|
||||
tabTypeLabel.setName("tabTypeLabel");
|
||||
panel4.add(tabTypeLabel, "cell 2 1");
|
||||
|
||||
//======== tabTypeToolBar ========
|
||||
{
|
||||
tabTypeToolBar.setFloatable(false);
|
||||
tabTypeToolBar.setName("tabTypeToolBar");
|
||||
|
||||
//---- underlinedTabTypeButton ----
|
||||
underlinedTabTypeButton.setText("underlined");
|
||||
underlinedTabTypeButton.setSelected(true);
|
||||
underlinedTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
underlinedTabTypeButton.setName("underlinedTabTypeButton");
|
||||
underlinedTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(underlinedTabTypeButton);
|
||||
|
||||
//---- cardTabTypeButton ----
|
||||
cardTabTypeButton.setText("card");
|
||||
cardTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
cardTabTypeButton.setName("cardTabTypeButton");
|
||||
cardTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(cardTabTypeButton);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.5.0.404" Java: "17" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
"$setComponentNames": true
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[grow,fill]para[fill]para[fill]"
|
||||
|
||||
@@ -144,13 +144,13 @@ public class IJThemesPanel
|
||||
// add core themes at beginning
|
||||
categories.put( themes.size(), "Core Themes" );
|
||||
if( showLight )
|
||||
themes.add( new IJThemeInfo( "Flat Light", null, false, null, null, null, null, null, FlatLightLaf.class.getName() ) );
|
||||
themes.add( new IJThemeInfo( "FlatLaf Light", null, false, null, null, null, null, null, FlatLightLaf.class.getName() ) );
|
||||
if( showDark )
|
||||
themes.add( new IJThemeInfo( "Flat Dark", null, true, null, null, null, null, null, FlatDarkLaf.class.getName() ) );
|
||||
themes.add( new IJThemeInfo( "FlatLaf Dark", null, true, null, null, null, null, null, FlatDarkLaf.class.getName() ) );
|
||||
if( showLight )
|
||||
themes.add( new IJThemeInfo( "Flat IntelliJ", null, false, null, null, null, null, null, FlatIntelliJLaf.class.getName() ) );
|
||||
themes.add( new IJThemeInfo( "FlatLaf IntelliJ", null, false, null, null, null, null, null, FlatIntelliJLaf.class.getName() ) );
|
||||
if( showDark )
|
||||
themes.add( new IJThemeInfo( "Flat Darcula", null, true, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
|
||||
themes.add( new IJThemeInfo( "FlatLaf Darcula", null, true, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
|
||||
|
||||
// add themes from directory
|
||||
categories.put( themes.size(), "Current Directory" );
|
||||
|
||||
@@ -475,7 +475,7 @@ public class FlatInspector
|
||||
appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) );
|
||||
|
||||
appendRow( buf, "Background", toString( c.getBackground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isForegroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Font", toString( c.getFont() ) + (c.isFontSet() ? "" : " NOT SET") );
|
||||
|
||||
if( c instanceof JComponent ) {
|
||||
|
||||
@@ -273,15 +273,31 @@ public class FlatSVGIcon
|
||||
// since the input stream is already loaded and parsed,
|
||||
// get diagram here and remove it from cache
|
||||
update();
|
||||
svgCache.remove( uri );
|
||||
synchronized( FlatSVGIcon.class ) {
|
||||
svgCache.remove( uri );
|
||||
}
|
||||
}
|
||||
|
||||
private static URI loadFromStream( InputStream in ) throws IOException {
|
||||
private static synchronized URI loadFromStream( InputStream in ) throws IOException {
|
||||
try( InputStream in2 = in ) {
|
||||
return svgUniverse.loadSVG( in2, "/flatlaf-stream-" + (streamNumber++) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the given icon.
|
||||
* <p>
|
||||
* If the icon has a color filter, then it is shared with the new icon.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public FlatSVGIcon( FlatSVGIcon icon ) {
|
||||
this( icon.name, icon.width, icon.height, icon.scale, icon.disabled, icon.classLoader, icon.uri );
|
||||
colorFilter = icon.colorFilter;
|
||||
diagram = icon.diagram;
|
||||
dark = icon.dark;
|
||||
}
|
||||
|
||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader, URI uri ) {
|
||||
this.name = name;
|
||||
this.width = width;
|
||||
@@ -464,7 +480,7 @@ public class FlatSVGIcon
|
||||
|
||||
if( url == null ) {
|
||||
loadFailed = true;
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
||||
LoggingFacade.INSTANCE.logConfig( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -475,7 +491,7 @@ public class FlatSVGIcon
|
||||
loadFailed = (diagram == null);
|
||||
}
|
||||
|
||||
static SVGDiagram loadSVG( URI uri ) {
|
||||
static synchronized SVGDiagram loadSVG( URI uri ) {
|
||||
// get from our cache
|
||||
SVGDiagram diagram = svgCache.get( uri );
|
||||
if( diagram != null )
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user