Compare commits

..

1 Commits

Author SHA1 Message Date
Karl Tauber
78a8035b92 Linux: rounded borders for popups (issue #949) 2025-01-27 17:15:38 +01:00
200 changed files with 6410 additions and 19821 deletions

View File

@@ -105,11 +105,11 @@ jobs:
distribution: temurin # pre-installed on ubuntu-latest distribution: temurin # pre-installed on ubuntu-latest
cache: gradle cache: gradle
- name: Publish snapshot to Sonatype Central - name: Publish snapshot to oss.sonatype.org
run: ./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false run: ./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
env: env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
release: release:
@@ -131,10 +131,10 @@ jobs:
cache: gradle cache: gradle
- name: Release a new stable version to Maven Central - name: Release a new stable version to Maven Central
run: ./gradlew publishToSonatype closeSonatypeStagingRepository :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
env: env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }} SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

View File

@@ -45,18 +45,18 @@ jobs:
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
- name: Publish snapshot to Sonatype Central - name: Publish snapshot to oss.sonatype.org
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
env: env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' ) if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )
- name: Release a new stable version to Maven Central - name: Release a new stable version to Maven Central
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease
env: env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }} SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )

View File

@@ -28,10 +28,10 @@ jobs:
distribution: temurin # pre-installed on ubuntu-latest distribution: temurin # pre-installed on ubuntu-latest
cache: gradle cache: gradle
- name: Publish PR snapshot to Sonatype Central - name: Publish PR snapshot to oss.sonatype.org
run: > run: >
./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false ./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
-Pgithub.event.pull_request.number=${{ github.event.pull_request.number }} -Pgithub.event.pull_request.number=${{ github.event.pull_request.number }}
env: env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}

1
.gitignore vendored
View File

@@ -5,7 +5,6 @@ build/
.project .project
.settings/ .settings/
.idea/ .idea/
.consulo/
out/ out/
*.iml *.iml
*.ipr *.ipr

View File

@@ -1,69 +1,21 @@
FlatLaf Change Log FlatLaf Change Log
================== ==================
## 3.6.1 ## 3.6-SNAPSHOT
- Extras: Support JSVG 2.0.0. Minimum JSVG version is now 1.6.0. (issue #997)
- FlatLaf window decorations (Windows 10/11 only): Improved diagonal window
resizing on top-left and top-right window corners. Top window resize area now
also covers iconify/maximize/close buttons. (issue #1015)
- ToggleButton: Styling `selectedForeground` did not work if `foreground` is
also styled. (issue #1017)
- JideSplitButton: Fixed updating popup when switching theme. (issue #1000)
- IntelliJ Themes: Fixed logging false errors when loading 3rd party
`.theme.json` files. (issue #990)
- Linux: Popups appeared in wrong position on multi-screen setup if primary
display is located below or right to secondary display. (see
[NetBeans issue #8532](https://github.com/apache/netbeans/issues/8532))
- macOS: Fixed popup flickering after theme change. (issue #1009)
- macOS with JetBrains Runtime: Fixed sometimes empty popups. (issue #1019)
## 3.6
#### New features and improvements #### New features and improvements
- macOS: Re-enabled rounded popup border (see PR #772) on macOS 14.4+ (was - macOS: Re-enabled rounded popup border (see PR #772) on macOS 14.4+ (was
disabled in 3.5.x). disabled in 3.5.x).
- Increased contrast of text for better readability: (PR #972; issue #762)
- In **FlatLaf Dark**, **FlatLaf Darcula** and many dark IntelliJ themes, made
all text colors brighter.
- In **FlatLaf Light**, **FlatLaf IntelliJ** and many light IntelliJ themes,
made disabled text colors slightly darker.
- In **FlatLaf macOS Light**, made disabled text colors darker.
- In **FlatLaf macOS Dark**, made text colors of "default" button and selected
ToggleButton lighter.
- CheckBox: Support styling indeterminate state of - CheckBox: Support styling indeterminate state of
[tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html). [tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html).
(PR #936; issue #919) (PR #936; issue #919)
- List: Support for alternate row highlighting. (PR #939) - List: Support for alternate row highlighting. (PR #939)
- Tree: Support for alternate row highlighting. (PR #903) - Tree: Support for alternate row highlighting. (PR #903)
- Tree: Support wide cell renderer. (issue #922) - Tree: Support wide cell renderer. (issue #922)
- ScrollBar: Use rounded thumb also on Windows (as on macOS and Linux) and made
thumb slightly darker/lighter. (issue #918)
- Extras: `FlatSVGIcon` color filters now can access painting component to - Extras: `FlatSVGIcon` color filters now can access painting component to
implement component state based color mappings. (issue #906) implement component state based color mappings. (issue #906)
- Linux: - Linux: Added `libflatlaf-linux-arm64.so` for Linux on ARM64. (issue #899)
- Rounded iconify/maximize/close buttons if using FlatLaf window decorations.
(PR #971)
- Added `libflatlaf-linux-arm64.so` for Linux on ARM64. (issue #899)
- Use X11 window manager events to resize window, if FlatLaf window
decorations are enabled. This gives FlatLaf windows a more "native" feeling.
(issue #866)
- IntelliJ Themes:
- Updated to latest versions and fixed various issues.
- Support customizing through properties files. (issue #824)
- SwingX: Support `JXTipOfTheDay` component. (issue #980)
- Support key prefixes for Linux desktop environments (e.g. `[gnome]`, `[kde]`
or `[xfce]`) in properties files. (issue #974)
- Support custom key prefixes (e.g. `[win10]` or `[test]`) in properties files.
(issue #649)
- Support multi-prefixed keys (e.g. `[dark][gnome]TitlePane.buttonBackground`).
The value is only used if all prefixes match current platform/theme.
- Support new component border color to indicate success state (set client
property `JComponent.outline` to `success`). (PR #982, issue #945)
- Fonts: Updated **Inter** to
[v4.1](https://github.com/rsms/inter/releases/tag/v4.1).
#### Fixed bugs #### Fixed bugs
@@ -75,63 +27,12 @@ FlatLaf Change Log
- PopupFactory: Fixed NPE on Windows 10 when `owner` is `null`. (issue #952) - PopupFactory: Fixed NPE on Windows 10 when `owner` is `null`. (issue #952)
- Popup: On Windows 10, drop shadow of heavy-weight popup was not updated if - Popup: On Windows 10, drop shadow of heavy-weight popup was not updated if
popup moved/resized. (issue #942) popup moved/resized. (issue #942)
- FlatLaf window decorations: - FlatLaf window decorations: Minimize and maximize icons were not shown for
- Minimize and maximize icons were not shown for custom scale factors less custom scale factors less than 100% (e.g. `-Dflatlaf.uiScale=75%`). (issue
than 100% (e.g. `-Dflatlaf.uiScale=75%`). (issue #951) #951)
- Linux: Fixed occasional maximizing of window when single-clicking the
window's title bar. (issue #637)
- Styling: MigLayout visual padding was not updated after applying style to
Button, ComboBox, Spinner, TextField (and subclasses) and ToggleButton. (issue
#965)
- Linux: Popups (menus and combobox lists) were not hidden when window is moved, - Linux: Popups (menus and combobox lists) were not hidden when window is moved,
resized, maximized, restored, iconified or switched to another window. (issue resized, maximized, restored, iconified or switched to another window. (issue
#962) #962)
- Fixed loading FlatLaf UI delegate classes when using FlatLaf in special
application where multiple class loaders are involved. E.g. in Eclipse plugin
or in LibreOffice extension. (issues #955 and #851)
- HTML: Fixed rendering of `<hr noshade>` in dark themes. (issue #932)
- TextComponents: `selectAllOnFocusPolicy` related changes:
- No longer select all text if selection (or caret position) was changed by
application and `selectAllOnFocusPolicy` is `once` (the default). (issue
#983)
- FormattedTextField and Spinner: `selectAllOnFocusPolicy = once` behaves now
as `always` (was `never` before), which means that all text is selected when
component gains focus. This is because of special behavior of
`JFormattedTextField` that did not allow implementation of `once`.
- Client property `JTextField.selectAllOnFocusPolicy` now also works on
(editable) `JComboBox` and on `JSpinner`.
- Added client property `JTextField.selectAllOnMouseClick` to override UI
property `TextComponent.selectAllOnMouseClick`. (issue #961)
- For `selectAllOnMouseClick = true`, clicking with the mouse into the text
field, to focus it, now always selects all text, even if
`selectAllOnFocusPolicy` is `once`.
#### Incompatibilities
- IntelliJ Themes:
- Theme prefix in `IntelliJTheme$ThemeLaf.properties` changed from
`[theme-name]` to `{theme-name}`.
- Renamed classes in package
`com.formdev.flatlaf.intellijthemes.materialthemeuilite` from `Flat<theme>`
to `FlatMT<theme>`.
- Removed `Gruvbox Dark Medium` and `Gruvbox Dark Soft` themes.
- Prefixed keys in properties files (e.g. `[dark]Button.background` or
`[win]Button.arc`) are now handled earlier than before. In previous versions,
prefixed keys always had higher priority than unprefixed keys and did always
overwrite unprefixed keys. Now prefixed keys are handled in same order as
unprefixed keys, which means that if a key is prefixed and unprefixed (e.g.
`[win]Button.arc` and `Button.arc`), the one which is last specified in
properties file is used.\
Following worked in previous versions, but now `Button.arc` is always `6`:
~~~properties
[win]Button.arc = 12
Button.arc = 6
~~~
This works in new (and old) versions:
~~~properties
Button.arc = 6
[win]Button.arc = 12
~~~
## 3.5.4 ## 3.5.4

100
README.md
View File

@@ -83,10 +83,10 @@ application.
### Snapshots ### Snapshots
FlatLaf snapshot binaries are available on FlatLaf snapshot binaries are available on
[Sonatype Central](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/com/formdev/flatlaf/). [Sonatype OSSRH](https://oss.sonatype.org/content/repositories/snapshots/com/formdev/flatlaf/).
To access the latest snapshot, change the FlatLaf version in your dependencies To access the latest snapshot, change the FlatLaf version in your dependencies
to `<version>-SNAPSHOT` (e.g. `3.7-SNAPSHOT`) and add the repository to `<version>-SNAPSHOT` (e.g. `0.27-SNAPSHOT`) and add the repository
`https://central.sonatype.com/repository/maven-snapshots/` to your build (see `https://oss.sonatype.org/content/repositories/snapshots/` to your build (see
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html) [Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
and and
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository) [Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
@@ -184,16 +184,11 @@ Applications using FlatLaf
relational data browsing tool relational data browsing tool
- ![Hot](images/hot.svg) [MagicPlot](https://magicplot.com/) (**commercial**) - - ![Hot](images/hot.svg) [MagicPlot](https://magicplot.com/) (**commercial**) -
Software for nonlinear fitting, plotting and data analysis Software for nonlinear fitting, plotting and data analysis
- [Constellation](https://www.constellation-app.com/) - Data Visualization and - ![New](images/new.svg) [Constellation](https://www.constellation-app.com/) -
Analytics (based on NetBeans platform) Data Visualization and Analytics (based on NetBeans platform)
- [Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI - ![New](images/new.svg)
[Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
client client
- ![New](images/new.svg)
[RedisFront](https://github.com/dromara/RedisFront/blob/master/README_EN.md) -
Cross-platform redis GUI
- ![New](images/new.svg)
[Zettelkasten](https://github.com/Zettelkasten-Team/Zettelkasten) - knowledge
management tool
### Security ### Security
@@ -202,9 +197,11 @@ Applications using FlatLaf
- ![Hot](images/hot.svg) - ![Hot](images/hot.svg)
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro) [Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
(**commercial**) - the leading software for web security testing (**commercial**) - the leading software for web security testing
- [Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software - ![New](images/new.svg)
[Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
reverse engineering (SRE) framework reverse engineering (SRE) framework
- [jadx](https://github.com/skylot/jadx) - Dex to Java decompiler - ![New](images/new.svg) [jadx](https://github.com/skylot/jadx) - Dex to Java
decompiler
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more - [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
FlatLaf themes to Burp Suite FlatLaf themes to Burp Suite
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks - [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
@@ -216,24 +213,19 @@ Applications using FlatLaf
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) - [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
- [KeyStore Explorer](https://keystore-explorer.org/) - [KeyStore Explorer](https://keystore-explorer.org/)
- [muCommander](https://github.com/mucommander/mucommander) - lightweight - ![New](images/new.svg)
[muCommander](https://github.com/mucommander/mucommander) - lightweight
cross-platform file manager cross-platform file manager
- [Guiffy](https://www.guiffy.com/) (**commercial**) - advanced cross-platform - ![New](images/new.svg) [Guiffy](https://www.guiffy.com/) (**commercial**) -
Diff/Merge advanced cross-platform Diff/Merge
- [HashGarten](https://github.com/jonelo/HashGarten) - cross-platform Swing GUI - ![New](images/new.svg) [HashGarten](https://github.com/jonelo/HashGarten) -
for Jacksum cross-platform Swing GUI for Jacksum
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) - - [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
IDE for Pseudo-Assembler IDE for Pseudo-Assembler
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming - [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
language created to learn programming language created to learn programming
- [lsfusion platform](https://github.com/lsfusion/platform) - information - [lsfusion platform](https://github.com/lsfusion/platform) - information
systems development platform systems development platform
- ![New](images/new.svg) [Consulo](https://github.com/consulo/consulo) - open
source cross-platform multi-language IDE (Java, .NET, JS, etc)
- [Convertigo](https://github.com/convertigo/convertigo) - low code & no code
mobile & web platform
- ![New](images/new.svg) [EduMIPS64](https://github.com/EduMIPS64/edumips64) -
visual MIPS64 CPU simulator
### Electrical ### Electrical
@@ -241,11 +233,6 @@ Applications using FlatLaf
designing, simulating and explaining digital circuits designing, simulating and explaining digital circuits
- [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) - - [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) -
Digital logic design tool and simulator Digital logic design tool and simulator
- ![New](images/new.svg) [OpenPnP](https://github.com/openpnp/openpnp) - SMT
Pick and Place Hardware and Software
- ![New](images/new.svg)
[TrainControl](https://github.com/bob123456678/TrainControl) - control Marklin
/ Trix / DCC digital model train layout
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) - - [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
for plotters, especially the wall-hanging polargraph for plotters, especially the wall-hanging polargraph
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI - [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
@@ -260,10 +247,8 @@ Applications using FlatLaf
- ![Hot](images/hot.svg) [jAlbum](https://jalbum.net/) (**commercial**) - - ![Hot](images/hot.svg) [jAlbum](https://jalbum.net/) (**commercial**) -
creates photo album websites creates photo album websites
- [MediathekView](https://mediathekview.de/) - search in media libraries of - ![New](images/new.svg) [MediathekView](https://mediathekview.de/) - search in
various German broadcasters media libraries of various German broadcasters
- ![New](images/new.svg) [Pixelitor](https://github.com/lbalazscs/Pixelitor) -
image editor
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit - [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
sequences sequences
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a - [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
@@ -280,23 +265,18 @@ Applications using FlatLaf
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with - [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
ease ease
### Modelling / Planning ### Modelling
- ![New](images/new.svg) [Gephi](https://github.com/gephi/gephi) - the Open - ![New](images/new.svg) [Astah](https://astah.net/) (**commercial**) - create
Graph Viz Platform UML, ER Diagram, Flowchart, Data Flow Diagram, Requirement Diagram, SysML
- [Astah](https://astah.net/) (**commercial**) - create UML, ER Diagram, diagrams and more
Flowchart, Data Flow Diagram, Requirement Diagram, SysML diagrams and more
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic - [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
Application System Application System
- ![New](images/new.svg) [StarPlan](https://www.progotec.de/) (**commercial**) -
die Stundenplan Software für Bildungseinrichtungen
- ![New](images/new.svg) [SSPlot](https://github.com/babaissarkar/ssplot) -
plotting utility for plotting CSV data
### Documents ### Documents
- [Big Faceless (BFO) PDF Viewer](https://bfo.com/) (**commercial**) - Swing PDF - ![New](images/new.svg) [Big Faceless (BFO) PDF Viewer](https://bfo.com/)
Viewer (**commercial**) - Swing PDF Viewer
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create, - [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
review and edit PDF documents review and edit PDF documents
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**) - [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
@@ -314,9 +294,6 @@ Applications using FlatLaf
### Business / Legal ### Business / Legal
- ![New](images/new.svg) ![Sponsor](images/sponsor.svg)
[Lisheane ERP](https://www.lisheane.ch/) (**commercial**) - backoffice
applikation
- ![Sponsor](images/sponsor.svg) - ![Sponsor](images/sponsor.svg)
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
- ![Sponsor](images/sponsor.svg) [Jeyla Studio](https://www.jeylastudio.com/) - - ![Sponsor](images/sponsor.svg) [Jeyla Studio](https://www.jeylastudio.com/) -
@@ -333,20 +310,20 @@ Applications using FlatLaf
### Messaging ### Messaging
- [Spark](https://github.com/igniterealtime/Spark) - cross-platform IM client - ![New](images/new.svg) [Spark](https://github.com/igniterealtime/Spark) -
optimized for businesses and organizations cross-platform IM client optimized for businesses and organizations
- [Chatty](https://github.com/chatty/chatty) - Twitch Chat Client - ![New](images/new.svg) [Chatty](https://github.com/chatty/chatty) - Twitch
Chat Client
### Gaming ### Gaming
- ![Sponsor](images/sponsor.svg) [BGBlitz](https://www.bgblitz.com/) - ![New](images/new.svg) ![Sponsor](images/sponsor.svg)
(**commercial**) - professional Backgammon [BGBlitz](https://www.bgblitz.com/) (**commercial**) - professional Backgammon
- ![New](images/new.svg) [josé](https://peteschaefer.github.io/jose/) - a - ![New](images/new.svg) [MCreator](https://github.com/MCreator/MCreator) -
graphical chess tool software used to make Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons,
- ![New](images/new.svg) [MCreator](https://github.com/MCreator/MCreator) - make and data packs without programming knowledge
Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons, and data packs - ![New](images/new.svg) [MapTool](https://github.com/RPTools/maptool) - virtual
- [MapTool](https://github.com/RPTools/maptool) - virtual Tabletop for playing Tabletop for playing role-playing games
role-playing games
- [MegaMek](https://github.com/MegaMek/megamek), - [MegaMek](https://github.com/MegaMek/megamek),
[MegaMekLab](https://github.com/MegaMek/megameklab) and [MegaMekLab](https://github.com/MegaMek/megameklab) and
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech [MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
@@ -358,7 +335,8 @@ Applications using FlatLaf
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of - [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
OSHI, to view information about the system and hardware OSHI, to view information about the system and hardware
- [Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) - - ![New](images/new.svg)
[Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
GUI for monitoring and managing various aspects of a Linux system GUI for monitoring and managing various aspects of a Linux system
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing - [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH - [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
@@ -367,8 +345,6 @@ Applications using FlatLaf
easy easy
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb - [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
and fastboot commands easier to use and fastboot commands easier to use
- ![New](images/new.svg) [Termora](https://github.com/TermoraDev/termora) -
Terminal emulator and SSH client
### Miscellaneous ### Miscellaneous

View File

@@ -16,7 +16,6 @@
import net.ltgt.gradle.errorprone.errorprone import net.ltgt.gradle.errorprone.errorprone
group = "com.formdev"
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
// for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT' // for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT'
@@ -50,7 +49,6 @@ println()
plugins { plugins {
alias( libs.plugins.gradle.nexus.publish.plugin )
alias( libs.plugins.errorprone ) apply false alias( libs.plugins.errorprone ) apply false
} }
@@ -145,20 +143,3 @@ allprojects {
} }
} }
} }
nexusPublishing {
repositories {
sonatype {
// see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/
nexusUrl = uri( "https://ossrh-staging-api.central.sonatype.com/service/local/" )
snapshotRepositoryUrl = uri( "https://central.sonatype.com/repository/maven-snapshots/" )
// get from gradle.properties
val sonatypeUsername: String? by project
val sonatypePassword: String? by project
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword
}
}
}

View File

@@ -86,26 +86,24 @@ publishing {
} }
} }
/*
repositories { repositories {
maven { maven {
name = "MavenCentral" name = "OSSRH"
val releasesRepoUrl = "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/" val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
val snapshotsRepoUrl = "https://central.sonatype.com/repository/maven-snapshots/" val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl ) url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
credentials { credentials {
// get from gradle.properties // get from gradle.properties
val sonatypeUsername: String? by project val ossrhUsername: String? by project
val sonatypePassword: String? by project val ossrhPassword: String? by project
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername username = System.getenv( "OSSRH_USERNAME" ) ?: ossrhUsername
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword password = System.getenv( "OSSRH_PASSWORD" ) ?: ossrhPassword
} }
} }
} }
*/
} }
signing { signing {

View File

@@ -1,7 +1,4 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

View File

@@ -1,5 +1,5 @@
#Signature file v4.1 #Signature file v4.1
#Version 3.6.1 #Version 3.5.2
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType" fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
@@ -24,7 +24,6 @@ fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHei
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth" fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
fld public final static java.lang.String OUTLINE = "JComponent.outline" fld public final static java.lang.String OUTLINE = "JComponent.outline"
fld public final static java.lang.String OUTLINE_ERROR = "error" fld public final static java.lang.String OUTLINE_ERROR = "error"
fld public final static java.lang.String OUTLINE_SUCCESS = "success"
fld public final static java.lang.String OUTLINE_WARNING = "warning" fld public final static java.lang.String OUTLINE_WARNING = "warning"
fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placeholderText" fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placeholderText"
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius" fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
@@ -41,7 +40,6 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY = "JTextFiel
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always" fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never" fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once" fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
fld public final static java.lang.String SELECT_ALL_ON_MOUSE_CLICK = "JTextField.selectAllOnMouseClick"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide" fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left" fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right" fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
@@ -109,7 +107,6 @@ fld public final static java.lang.String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.ti
fld public final static java.lang.String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize" fld public final static java.lang.String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize"
fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle" fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle"
fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection" fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection"
fld public final static java.lang.String TREE_WIDE_CELL_RENDERER = "JTree.wideCellRenderer"
fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection" fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection"
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations" fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"
fld public final static java.lang.String WINDOW_STYLE = "Window.style" fld public final static java.lang.String WINDOW_STYLE = "Window.style"
@@ -223,11 +220,8 @@ meth public static java.lang.String getPreferredFontFamily()
meth public static java.lang.String getPreferredLightFontFamily() meth public static java.lang.String getPreferredLightFontFamily()
meth public static java.lang.String getPreferredMonospacedFontFamily() meth public static java.lang.String getPreferredMonospacedFontFamily()
meth public static java.lang.String getPreferredSemiboldFontFamily() meth public static java.lang.String getPreferredSemiboldFontFamily()
meth public static java.lang.String getUIKeyLightOrDarkPrefix(boolean)
meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleableInfos(javax.swing.JComponent) meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleableInfos(javax.swing.JComponent)
meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults() meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults()
meth public static java.util.Set<java.lang.String> getUIKeyPlatformPrefixes()
meth public static java.util.Set<java.lang.String> getUIKeySpecialPrefixes()
meth public static java.util.function.Function<java.lang.String,java.awt.Color> getSystemColorGetter() meth public static java.util.function.Function<java.lang.String,java.awt.Color> getSystemColorGetter()
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float) meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
meth public static void disableWindowsD3Donscreen() meth public static void disableWindowsD3Donscreen()
@@ -261,7 +255,7 @@ meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.Strin
meth public void uninitialize() meth public void uninitialize()
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>) meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
supr javax.swing.plaf.basic.BasicLookAndFeel supr javax.swing.plaf.basic.BasicLookAndFeel
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,linuxPopupMenuCanceler,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,uiKeyPlatformPrefixes,uiKeySpecialPrefixes,updateUIPending hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,updateUIPending
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
@@ -324,7 +318,7 @@ meth public static boolean setup(java.io.InputStream)
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme) meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
supr java.lang.Object supr java.lang.Object
hfds checkboxDuplicateColors,checkboxKeyMapping,jsonColors,jsonIcons,jsonUI,namedColors,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludesContains,uiKeyExcludesStartsWith,uiKeyInverseMapping,uiKeyMapping hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludes,uiKeyInverseMapping,uiKeyMapping
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
outer com.formdev.flatlaf.IntelliJTheme outer com.formdev.flatlaf.IntelliJTheme
@@ -419,7 +413,6 @@ innr public static Fade
innr public static HSLChange innr public static HSLChange
innr public static HSLIncreaseDecrease innr public static HSLIncreaseDecrease
innr public static Mix innr public static Mix
innr public static Mix2
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[]) meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
meth public static float clamp(float) meth public static float clamp(float)
meth public static float luma(java.awt.Color) meth public static float luma(java.awt.Color)
@@ -481,16 +474,6 @@ meth public java.lang.String toString()
meth public void apply(float[]) meth public void apply(float[])
supr java.lang.Object supr java.lang.Object
CLSS public static com.formdev.flatlaf.util.ColorFunctions$Mix2
outer com.formdev.flatlaf.util.ColorFunctions
cons public init(java.awt.Color,float)
fld public final float weight
fld public final java.awt.Color color1
intf com.formdev.flatlaf.util.ColorFunctions$ColorFunction
meth public java.lang.String toString()
meth public void apply(float[])
supr java.lang.Object
CLSS public com.formdev.flatlaf.util.CubicBezierEasing CLSS public com.formdev.flatlaf.util.CubicBezierEasing
cons public init(float,float,float,float) cons public init(float,float,float,float)
fld public final static com.formdev.flatlaf.util.CubicBezierEasing EASE fld public final static com.formdev.flatlaf.util.CubicBezierEasing EASE
@@ -772,7 +755,6 @@ supr java.lang.Object
CLSS public com.formdev.flatlaf.util.SystemInfo CLSS public com.formdev.flatlaf.util.SystemInfo
cons public init() cons public init()
fld public final static boolean isAARCH64 fld public final static boolean isAARCH64
fld public final static boolean isGNOME
fld public final static boolean isJava_11_orLater fld public final static boolean isJava_11_orLater
fld public final static boolean isJava_12_orLater fld public final static boolean isJava_12_orLater
fld public final static boolean isJava_15_orLater fld public final static boolean isJava_15_orLater
@@ -789,7 +771,6 @@ fld public final static boolean isMacOS_10_11_ElCapitan_orLater
fld public final static boolean isMacOS_10_14_Mojave_orLater fld public final static boolean isMacOS_10_14_Mojave_orLater
fld public final static boolean isMacOS_10_15_Catalina_orLater fld public final static boolean isMacOS_10_15_Catalina_orLater
fld public final static boolean isProjector fld public final static boolean isProjector
fld public final static boolean isUnknownOS
fld public final static boolean isWebswing fld public final static boolean isWebswing
fld public final static boolean isWinPE fld public final static boolean isWinPE
fld public final static boolean isWindows fld public final static boolean isWindows

View File

@@ -21,8 +21,6 @@ import java.awt.IllegalComponentStateException;
import java.awt.Window; import java.awt.Window;
import java.util.Objects; import java.util.Objects;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
/** /**
@@ -222,7 +220,6 @@ public interface FlatClientProperties
* <strong>Allowed Values</strong> * <strong>Allowed Values</strong>
* {@link #OUTLINE_ERROR}, * {@link #OUTLINE_ERROR},
* {@link #OUTLINE_WARNING}, * {@link #OUTLINE_WARNING},
* {@link #OUTLINE_SUCCESS},
* any color (type {@link java.awt.Color}) or * any color (type {@link java.awt.Color}) or
* an array of two colors (type {@link java.awt.Color}[2]) where the first color * an array of two colors (type {@link java.awt.Color}[2]) where the first color
* is for focused state and the second for unfocused state * is for focused state and the second for unfocused state
@@ -243,14 +240,6 @@ public interface FlatClientProperties
*/ */
String OUTLINE_WARNING = "warning"; String OUTLINE_WARNING = "warning";
/**
* Paint the component border in another color (usually greenish) to indicate a success.
*
* @see #OUTLINE
* @since 3.6
*/
String OUTLINE_SUCCESS = "success";
/** /**
* Specifies a callback that is invoked to check whether a component is permanent focus owner. * Specifies a callback that is invoked to check whether a component is permanent focus owner.
* Used to paint focus indicators. * Used to paint focus indicators.
@@ -395,6 +384,7 @@ public interface FlatClientProperties
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used. * If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used. * If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
* <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported. * <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported.
* <li><strong>Linux</strong> (since FlatLaf 3.6): Any corner radius is supported.
* </ul> * </ul>
* <strong>Component</strong> {@link javax.swing.JComponent}<br> * <strong>Component</strong> {@link javax.swing.JComponent}<br>
* <strong>Value type</strong> {@link java.lang.Integer}<br> * <strong>Value type</strong> {@link java.lang.Integer}<br>
@@ -413,6 +403,7 @@ public interface FlatClientProperties
* Supported platforms: * Supported platforms:
* <ul> * <ul>
* <li><strong>macOS</strong> (10.14 and later) * <li><strong>macOS</strong> (10.14 and later)
* <li><strong>Linux</strong> (since FlatLaf 3.6)
* </ul> * </ul>
* <strong>Component</strong> {@link javax.swing.JComponent}<br> * <strong>Component</strong> {@link javax.swing.JComponent}<br>
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br> * <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br>
@@ -1211,15 +1202,12 @@ public interface FlatClientProperties
/** /**
* Specifies whether all text is selected when the text component gains focus. * Specifies whether all text is selected when the text component gains focus.
* <p> * <p>
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses), * <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
* {@link javax.swing.JComboBox} (since 3.6) and {@link javax.swing.JSpinner} (since 3.6)<br>
* <strong>Value type</strong> {@link java.lang.String}<br> * <strong>Value type</strong> {@link java.lang.String}<br>
* <strong>Allowed Values</strong> * <strong>Allowed Values</strong>
* {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER}, * {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or * {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS} * {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
*
* @see #SELECT_ALL_ON_MOUSE_CLICK
*/ */
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy"; String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
@@ -1234,12 +1222,6 @@ public interface FlatClientProperties
* Select all text when the text component gains focus for the first time * Select all text when the text component gains focus for the first time
* and selection was not modified (is at end of text). * and selection was not modified (is at end of text).
* This is the default. * This is the default.
* <p>
* <b>Limitations:</b>
* For {@link JFormattedTextField} and {@link JSpinner} this behaves
* as {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}.
* This is because of special behavior of {@link JFormattedTextField}
* that did not allow implementation of {@code "once"}.
* *
* @see #SELECT_ALL_ON_FOCUS_POLICY * @see #SELECT_ALL_ON_FOCUS_POLICY
*/ */
@@ -1252,19 +1234,6 @@ public interface FlatClientProperties
*/ */
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"; String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
/**
* Specifies whether all text is selected when when clicking with the mouse
* into the text field (and if "select all on focus" policy is enabled).
* <p>
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses),
* {@link javax.swing.JComboBox} and {@link javax.swing.JSpinner}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*
* @see #SELECT_ALL_ON_FOCUS_POLICY
* @since 3.6
*/
String SELECT_ALL_ON_MOUSE_CLICK = "JTextField.selectAllOnMouseClick";
/** /**
* Placeholder text that is only painted if the text field is empty. * Placeholder text that is only painted if the text field is empty.
* <p> * <p>

View File

@@ -37,7 +37,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@@ -45,7 +44,6 @@ import java.util.MissingResourceException;
import java.util.Properties; import java.util.Properties;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
@@ -102,8 +100,6 @@ public abstract class FlatLaf
private static Map<String, String> globalExtraDefaults; private static Map<String, String> globalExtraDefaults;
private Map<String, String> extraDefaults; private Map<String, String> extraDefaults;
private static Function<String, Color> systemColorGetter; private static Function<String, Color> systemColorGetter;
private static Set<String> uiKeyPlatformPrefixes;
private static Set<String> uiKeySpecialPrefixes;
private String desktopPropertyName; private String desktopPropertyName;
private String desktopPropertyName2; private String desktopPropertyName2;
@@ -525,10 +521,10 @@ public abstract class FlatLaf
// load defaults from properties // load defaults from properties
List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading(); List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading();
if( lafClassesForDefaultsLoading == null ) if( lafClassesForDefaultsLoading != null )
lafClassesForDefaultsLoading = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() ); UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), isDark(), defaults );
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, else
this::applyAdditionalProperties, getAdditionalDefaults(), isDark(), defaults ); UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults );
// setup default font after loading defaults from properties // setup default font after loading defaults from properties
// to allow defining "defaultFont" in properties // to allow defining "defaultFont" in properties
@@ -545,6 +541,9 @@ public abstract class FlatLaf
// initialize text antialiasing // initialize text antialiasing
putAATextInfo( defaults ); putAATextInfo( defaults );
// apply additional defaults (e.g. from IntelliJ themes)
applyAdditionalDefaults( defaults );
// allow addons modifying UI defaults // allow addons modifying UI defaults
for( FlatDefaultsAddon addon : addons ) for( FlatDefaultsAddon addon : addons )
addon.afterDefaultsLoading( this, defaults ); addon.afterDefaultsLoading( this, defaults );
@@ -554,9 +553,6 @@ public abstract class FlatLaf
return UIScale.getUserScaleFactor(); return UIScale.getUserScaleFactor();
} ); } );
// add lazy UI delegate class loading (if necessary)
addLazyUIdelegateClassLoading( defaults );
if( postInitialization != null ) { if( postInitialization != null ) {
postInitialization.accept( defaults ); postInitialization.accept( defaults );
postInitialization = null; postInitialization = null;
@@ -565,8 +561,7 @@ public abstract class FlatLaf
return defaults; return defaults;
} }
// apply additional properties (e.g. from IntelliJ themes) void applyAdditionalDefaults( UIDefaults defaults ) {
void applyAdditionalProperties( Properties properties ) {
} }
protected List<Class<?>> getLafClassesForDefaultsLoading() { protected List<Class<?>> getLafClassesForDefaultsLoading() {
@@ -755,53 +750,6 @@ public abstract class FlatLaf
} }
} }
/**
* Handle UI delegate classes if running in special application where multiple class loaders are involved.
* E.g. in Eclipse plugin or in LibreOffice extension.
* <p>
* Problem: Swing runs in Java's system classloader and FlatLaf is loaded in plugin classloader.
* When Swing tries to load UI delegate class in {@link UIDefaults#getUIClass(String, ClassLoader)},
* invoked from {@link UIDefaults#getUI(JComponent)}, it uses the component's classloader,
* which is Java's system classloader for core Swing components,
* and can not find FlatLaf UI delegates.
* <p>
* Solution: Add lazy values for UI delegate class names.
* Those lazy values use FlatLaf classloader to load UI delegate class.
* This is similar to what {@link UIDefaults#getUIClass(String, ClassLoader)} does.
* <p>
* Not using {@code defaults.put( "ClassLoader", FlatLaf.class.getClassLoader() )},
* which would work for FlatLaf UI delegates, but it would break custom
* UI delegates used in other classloaders.
*/
private static void addLazyUIdelegateClassLoading( UIDefaults defaults ) {
if( FlatLaf.class.getClassLoader() == ClassLoader.getSystemClassLoader() )
return; // not necessary
Map<String, LazyValue> map = new HashMap<>();
for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
Object key = e.getKey();
Object value = e.getValue();
if( key instanceof String && ((String)key).endsWith( "UI" ) &&
value instanceof String && !defaults.containsKey( value ) )
{
String className = (String) value;
map.put( className, (LazyValue) t -> {
try {
Class<?> uiClass = FlatLaf.class.getClassLoader().loadClass( className );
if( ComponentUI.class.isAssignableFrom( uiClass ) )
return uiClass;
} catch( ClassNotFoundException ex ) {
// ignore
}
// let UIDefaults.getUIClass() try to load UI delegate class
return null;
} );
}
}
defaults.putAll( map );
}
private void putAATextInfo( UIDefaults defaults ) { private void putAATextInfo( UIDefaults defaults ) {
if ( SystemInfo.isMacOS && SystemInfo.isJetBrainsJVM ) { if ( SystemInfo.isMacOS && SystemInfo.isJetBrainsJVM ) {
// The awt.font.desktophints property suggests sub-pixel anti-aliasing // The awt.font.desktophints property suggests sub-pixel anti-aliasing
@@ -1126,92 +1074,6 @@ public abstract class FlatLaf
FlatLaf.systemColorGetter = systemColorGetter; FlatLaf.systemColorGetter = systemColorGetter;
} }
/**
* Returns UI key prefix, used in FlatLaf properties files, for light or dark themes.
* Return value is either {@code [light]} or {@code [dark]}.
*
* @since 3.6
*/
public static String getUIKeyLightOrDarkPrefix( boolean dark ) {
return dark ? "[dark]" : "[light]";
}
/**
* Returns set of UI key prefixes, used in FlatLaf properties files, for current platform.
* If UI keys in properties files start with a prefix (e.g. {@code [someprefix]Button.background}),
* then they are only used if that prefix is contained in this set
* (or is one of {@code [light]} or {@code [dark]} depending on current theme).
* <p>
* By default, the set contains one or more of following prefixes:
* <ul>
* <li>{@code [win]} on Windows
* <li>{@code [mac]} on macOS
* <li>{@code [linux]} on Linux
* <li>{@code [unknown]} on other platforms
* <li>{@code [gnome]} on Linux with GNOME desktop environment
* <li>{@code [kde]} on Linux with KDE desktop environment
* <li>on Linux, the value of the environment variable {@code XDG_CURRENT_DESKTOP},
* split at colons and converted to lower case (e.g. if value of {@code XDG_CURRENT_DESKTOP}
* is {@code ubuntu:GNOME}, then {@code [ubuntu]} and {@code [gnome]})
* </ul>
* <p>
* You can add own prefixes to the set.
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
*
* @since 3.6
*/
public static Set<String> getUIKeyPlatformPrefixes() {
if( uiKeyPlatformPrefixes == null ) {
uiKeyPlatformPrefixes = new HashSet<>();
uiKeyPlatformPrefixes.add(
SystemInfo.isWindows ? "[win]" :
SystemInfo.isMacOS ? "[mac]" :
SystemInfo.isLinux ? "[linux]" : "[unknown]" );
// Linux
if( SystemInfo.isLinux ) {
if( SystemInfo.isGNOME )
uiKeyPlatformPrefixes.add( "[gnome]" );
else if( SystemInfo.isKDE )
uiKeyPlatformPrefixes.add( "[kde]" );
// add values from XDG_CURRENT_DESKTOP for other desktops
String desktop = System.getenv( "XDG_CURRENT_DESKTOP" );
if( desktop != null ) {
// XDG_CURRENT_DESKTOP is a colon-separated list of strings
// https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-onlyshowin
// e.g. "ubuntu:GNOME" on Ubuntu 24.10 or "GNOME-Classic:GNOME" on CentOS 7
for( String desk : StringUtils.split( desktop.toLowerCase( Locale.ENGLISH ), ':', true, true ) )
uiKeyPlatformPrefixes.add( '[' + desk + ']' );
}
}
}
return uiKeyPlatformPrefixes;
}
/**
* Returns set of special UI key prefixes, used in FlatLaf properties files.
* Unlike other prefixes, properties with special prefixes are preserved.
* You can access them using `UIManager`. E.g. `UIManager.get( "[someSpecialPrefix]someKey" )`.
* <p>
* By default, the set contains following special prefixes:
* <ul>
* <li>{@code [style]}
* </ul>
* <p>
* You can add own prefixes to the set.
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
*
* @since 3.6
*/
public static Set<String> getUIKeySpecialPrefixes() {
if( uiKeySpecialPrefixes == null ) {
uiKeySpecialPrefixes = new HashSet<>();
uiKeySpecialPrefixes.add( "[style]" );
}
return uiKeySpecialPrefixes;
}
private static void reSetLookAndFeel() { private static void reSetLookAndFeel() {
EventQueue.invokeLater( () -> { EventQueue.invokeLater( () -> {
LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); LookAndFeel lookAndFeel = UIManager.getLookAndFeel();

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf; package com.formdev.flatlaf;
import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -24,16 +25,20 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import javax.swing.UIDefaults;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.json.Json; import com.formdev.flatlaf.json.Json;
import com.formdev.flatlaf.json.ParseException; import com.formdev.flatlaf.json.ParseException;
import com.formdev.flatlaf.util.ColorFunctions;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
@@ -58,11 +63,13 @@ public class IntelliJTheme
public final boolean dark; public final boolean dark;
public final String author; public final String author;
private Map<String, String> jsonColors; private final boolean isMaterialUILite;
private Map<String, Object> jsonUI;
private Map<String, Object> jsonIcons;
private Map<String, String> namedColors = Collections.emptyMap(); private Map<String, String> colors;
private Map<String, Object> ui;
private Map<String, Object> icons;
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
/** /**
* Loads a IntelliJ .theme.json file from the given input stream, * Loads a IntelliJ .theme.json file from the given input stream,
@@ -131,90 +138,94 @@ public class IntelliJTheme
dark = Boolean.parseBoolean( (String) json.get( "dark" ) ); dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
author = (String) json.get( "author" ); author = (String) json.get( "author" );
jsonColors = (Map<String, String>) json.get( "colors" ); isMaterialUILite = author.equals( "Mallowigi" );
jsonUI = (Map<String, Object>) json.get( "ui" );
jsonIcons = (Map<String, Object>) json.get( "icons" ); colors = (Map<String, String>) json.get( "colors" );
ui = (Map<String, Object>) json.get( "ui" );
icons = (Map<String, Object>) json.get( "icons" );
} }
private void applyProperties( Properties properties ) { private void applyProperties( UIDefaults defaults ) {
if( jsonUI == null ) if( ui == null )
return; return;
put( properties, "Component.isIntelliJTheme", "true" ); defaults.put( "Component.isIntelliJTheme", true );
// enable button shadows // enable button shadows
put( properties, "Button.paintShadow", "true" ); defaults.put( "Button.paintShadow", true );
put( properties, "Button.shadowWidth", dark ? "2" : "1" ); defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
Map<String, String> themeSpecificProps = removeThemeSpecificProps( properties ); Map<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
Set<String> jsonUIKeys = new HashSet<>();
// Json node "colors" loadNamedColors( defaults );
loadNamedColors( properties, jsonUIKeys );
// convert Json "ui" structure to UI properties // convert Json "ui" structure to UI defaults
for( Map.Entry<String, Object> e : jsonUI.entrySet() ) ArrayList<Object> defaultsKeysCache = new ArrayList<>();
apply( e.getKey(), e.getValue(), properties, jsonUIKeys ); Set<String> uiKeys = new HashSet<>();
for( Map.Entry<String, Object> e : ui.entrySet() )
apply( e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
// set FlatLaf variables applyColorPalette( defaults );
copyIfSetInJson( properties, jsonUIKeys, "@background", "Panel.background", "*.background" ); applyCheckBoxColors( defaults );
copyIfSetInJson( properties, jsonUIKeys, "@foreground", "CheckBox.foreground", "*.foreground" );
copyIfSetInJson( properties, jsonUIKeys, "@accentBaseColor",
"ColorPalette.accent", // Material UI Lite, Hiberbee
"ColorPalette.accentColor", // Dracula, One Dark
"ProgressBar.foreground",
"*.selectionBackground" );
copyIfSetInJson( properties, jsonUIKeys, "@accentUnderlineColor", "*.underlineColor", "TabbedPane.underlineColor" );
copyIfSetInJson( properties, jsonUIKeys, "@selectionBackground", "*.selectionBackground" );
copyIfSetInJson( properties, jsonUIKeys, "@selectionForeground", "*.selectionForeground" );
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveBackground", "*.selectionInactiveBackground" );
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveForeground", "*.selectionInactiveForeground" );
// Json node "icons/ColorPalette"
applyIconsColorPalette( properties );
// apply "CheckBox.icon." colors
applyCheckBoxColors( properties );
// copy values // copy values
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) { for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
Object value = properties.get( e.getValue() ); Object value = defaults.get( e.getValue() );
if( value != null ) if( value != null )
put( properties, e.getKey(), value ); defaults.put( e.getKey(), value );
} }
// IDEA does not paint button background if disabled, but FlatLaf does // IDEA does not paint button background if disabled, but FlatLaf does
put( properties, "Button.disabledBackground", "@disabledBackground" ); Object panelBackground = defaults.get( "Panel.background" );
put( properties, "ToggleButton.disabledBackground", "@disabledBackground" ); defaults.put( "Button.disabledBackground", panelBackground );
defaults.put( "ToggleButton.disabledBackground", panelBackground );
// fix Button // fix Button borders
fixStartEnd( properties, jsonUIKeys, "Button.startBackground", "Button.endBackground", "Button.background" ); copyIfNotSet( defaults, "Button.focusedBorderColor", "Component.focusedBorderColor", uiKeys );
fixStartEnd( properties, jsonUIKeys, "Button.startBorderColor", "Button.endBorderColor", "Button.borderColor" ); defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
fixStartEnd( properties, jsonUIKeys, "Button.default.startBackground", "Button.default.endBackground", "Button.default.background" ); defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
fixStartEnd( properties, jsonUIKeys, "Button.default.startBorderColor", "Button.default.endBorderColor", "Button.default.borderColor" );
// 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 )
helpButtonBackground = defaults.get( "Button.background" );
if( helpButtonBorderColor == null )
helpButtonBorderColor = defaults.get( "Button.borderColor" );
defaults.put( "HelpButton.background", helpButtonBackground );
defaults.put( "HelpButton.borderColor", helpButtonBorderColor );
defaults.put( "HelpButton.disabledBackground", panelBackground );
defaults.put( "HelpButton.disabledBorderColor", defaults.get( "Button.disabledBorderColor" ) );
defaults.put( "HelpButton.focusedBorderColor", defaults.get( "Button.focusedBorderColor" ) );
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
// IDEA uses TextField.background for editable ComboBox and Spinner // IDEA uses TextField.background for editable ComboBox and Spinner
Object textFieldBackground = get( properties, themeSpecificProps, "TextField.background" ); Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" );
put( properties, "ComboBox.editableBackground", textFieldBackground ); defaults.put( "ComboBox.editableBackground", textFieldBackground );
put( properties, "Spinner.background", textFieldBackground ); defaults.put( "Spinner.background", textFieldBackground );
// Spinner arrow button always has same colors as ComboBox arrow button
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
defaults.put( "Spinner.buttonArrowColor", defaults.get( "ComboBox.buttonArrowColor" ) );
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
// some themes specify colors for TextField.background, but forget to specify it for other components // some themes specify colors for TextField.background, but forget to specify it for other components
// (probably because those components are not used in IntelliJ IDEA) // (probably because those components are not used in IntelliJ IDEA)
putAll( properties, textFieldBackground, putAll( defaults, textFieldBackground,
"EditorPane.background", "EditorPane.background",
"FormattedTextField.background", "FormattedTextField.background",
"PasswordField.background", "PasswordField.background",
"TextArea.background", "TextArea.background",
"TextPane.background" "TextPane.background"
); );
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionBackground" ), putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ),
"EditorPane.selectionBackground", "EditorPane.selectionBackground",
"FormattedTextField.selectionBackground", "FormattedTextField.selectionBackground",
"PasswordField.selectionBackground", "PasswordField.selectionBackground",
"TextArea.selectionBackground", "TextArea.selectionBackground",
"TextPane.selectionBackground" "TextPane.selectionBackground"
); );
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionForeground" ), putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ),
"EditorPane.selectionForeground", "EditorPane.selectionForeground",
"FormattedTextField.selectionForeground", "FormattedTextField.selectionForeground",
"PasswordField.selectionForeground", "PasswordField.selectionForeground",
@@ -224,7 +235,7 @@ public class IntelliJTheme
// fix disabled and not-editable backgrounds for text components, combobox and spinner // fix disabled and not-editable backgrounds for text components, combobox and spinner
// (IntelliJ IDEA does not use those colors; instead it used background color of parent) // (IntelliJ IDEA does not use those colors; instead it used background color of parent)
putAll( properties, "@disabledBackground", putAll( defaults, panelBackground,
"ComboBox.disabledBackground", "ComboBox.disabledBackground",
"EditorPane.disabledBackground", "EditorPane.inactiveBackground", "EditorPane.disabledBackground", "EditorPane.inactiveBackground",
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground", "FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
@@ -235,148 +246,132 @@ public class IntelliJTheme
"TextPane.disabledBackground", "TextPane.inactiveBackground" "TextPane.disabledBackground", "TextPane.inactiveBackground"
); );
// fix ToggleButton
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
defaults.put( "ToggleButton.startBackground", defaults.get( "Button.startBackground" ) );
if( !uiKeys.contains( "ToggleButton.endBackground" ) && !uiKeys.contains( "*.endBackground" ) )
defaults.put( "ToggleButton.endBackground", defaults.get( "Button.endBackground" ) );
if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) )
defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) );
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter) // fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
put( properties, "Desktop.background", dark ? "lighten($Panel.background,5%)" : "darken($Panel.background,5%)" ); Color desktopBackgroundBase = defaults.getColor( "Panel.background" );
Color desktopBackground = ColorFunctions.applyFunctions( desktopBackgroundBase,
new ColorFunctions.HSLIncreaseDecrease( 2, dark, 5, false, true ) );
defaults.put( "Desktop.background", new ColorUIResource( desktopBackground ) );
// fix List and Table background colors in Material UI Lite themes
if( isMaterialUILite ) {
defaults.put( "List.background", defaults.get( "Tree.background" ) );
defaults.put( "Table.background", defaults.get( "Tree.background" ) );
}
// limit tree row height // limit tree row height
String rowHeightStr = (String) properties.get( "Tree.rowHeight" ); int rowHeight = defaults.getInt( "Tree.rowHeight" );
int rowHeight = (rowHeightStr != null) ? Integer.parseInt( rowHeightStr ) : 0;
if( rowHeight > 22 ) if( rowHeight > 22 )
put( properties, "Tree.rowHeight", "22" ); defaults.put( "Tree.rowHeight", 22 );
// get (and remove) theme specific wildcard replacements, which override all other properties that end with same suffix // get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix
HashMap<String, String> wildcardProps = new HashMap<>(); HashMap<String, Object> wildcards = new HashMap<>();
Iterator<Map.Entry<String, String>> it = themeSpecificProps.entrySet().iterator(); Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
while( it.hasNext() ) { while( it.hasNext() ) {
Map.Entry<String, String> e = it.next(); Entry<Object, Object> e = it.next();
String key = e.getKey(); String key = (String) e.getKey();
if( key.startsWith( "*." ) ) { if( key.startsWith( "*." ) ) {
wildcardProps.put( key, e.getValue() ); wildcards.put( key.substring( "*.".length() ), e.getValue() );
it.remove(); it.remove();
} }
} }
// override properties with theme specific wildcard replacements // override UI defaults with theme specific wildcard replacements
if( !wildcardProps.isEmpty() ) { if( !wildcards.isEmpty() ) {
for( Map.Entry<String, String> e : wildcardProps.entrySet() ) for( Object key : defaults.keySet().toArray() ) {
applyWildcard( properties, e.getKey(), e.getValue() ); int dot;
if( !(key instanceof String) ||
(dot = ((String)key).lastIndexOf( '.' )) < 0 )
continue;
String wildcardKey = ((String)key).substring( dot + 1 );
Object wildcardValue = wildcards.get( wildcardKey );
if( wildcardValue != null )
defaults.put( key, wildcardValue );
}
} }
// apply theme specific properties at the end to allow overwriting // apply theme specific UI defaults at the end to allow overwriting
for( Map.Entry<String, String> e : themeSpecificProps.entrySet() ) { for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
String key = e.getKey(); Object key = e.getKey();
String value = e.getValue(); Object value = e.getValue();
// append styles to existing styles // append styles to existing styles
if( key.startsWith( "[style]" ) ) { if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
String oldValue = (String) properties.get( key ); Object oldValue = defaults.get( key );
if( oldValue != null ) if( oldValue != null )
value = oldValue + "; " + value; value = oldValue + "; " + value;
} }
put( properties, key, value ); defaults.put( key, value );
} }
// let Java release memory // let Java release memory
jsonColors = null; colors = null;
jsonUI = null; ui = null;
jsonIcons = null; icons = null;
} }
private String get( Properties properties, Map<String, String> themeSpecificProps, String key ) { private Object get( UIDefaults defaults, Map<Object, Object> themeSpecificDefaults, String key ) {
return themeSpecificProps.getOrDefault( key, (String) properties.get( key ) ); return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
} }
private void put( Properties properties, Object key, Object value ) { private void putAll( UIDefaults defaults, Object value, String... keys ) {
if( value != null )
properties.put( key, value );
else
properties.remove( key );
}
private void putAll( Properties properties, Object value, String... keys ) {
for( String key : keys ) for( String key : keys )
put( properties, key, value ); defaults.put( key, value );
} }
private void copyIfSetInJson( Properties properties, Set<String> jsonUIKeys, String destKey, String... srcKeys ) { private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
for( String srcKey : srcKeys ) { // search for theme specific UI defaults keys
if( jsonUIKeys.contains( srcKey ) ) {
Object value = properties.get( srcKey );
if( value != null ) {
put( properties, destKey, value );
break;
}
}
}
}
private void fixStartEnd( Properties properties, Set<String> jsonUIKeys, String startKey, String endKey, String key ) {
if( jsonUIKeys.contains( startKey ) && jsonUIKeys.contains( endKey ) )
put( properties, key, "$" + startKey );
}
private Map<String, String> removeThemeSpecificProps( Properties properties ) {
// search for theme specific properties keys
ArrayList<String> themeSpecificKeys = new ArrayList<>(); ArrayList<String> themeSpecificKeys = new ArrayList<>();
for( Object key : properties.keySet() ) { for( Object key : defaults.keySet() ) {
if( ((String)key).startsWith( "{" ) ) if( key instanceof String && ((String)key).startsWith( "[" ) && !((String)key).startsWith( "[style]" ) )
themeSpecificKeys.add( (String) key ); themeSpecificKeys.add( (String) key );
} }
// special prefixes (priority from highest to lowest) // remove theme specific UI defaults and remember only those for current theme
String currentThemePrefix = '{' + name.replace( ' ', '_' ) + '}'; Map<Object, Object> themeSpecificDefaults = new HashMap<>();
String currentThemeAndAuthorPrefix = '{' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + '}'; String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
String currentAuthorPrefix = "{author-" + author.replace( ' ', '_' ) + '}'; String currentThemeAndAuthorPrefix = '[' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + ']';
String lightOrDarkPrefix = dark ? "{*-dark}" : "{*-light}"; String currentAuthorPrefix = "[author-" + author.replace( ' ', '_' ) + ']';
String allThemesPrefix = "{*}"; String allThemesPrefix = "[*]";
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, lightOrDarkPrefix, allThemesPrefix }; String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix };
// collect values for special prefixes in its own maps
@SuppressWarnings( "unchecked" )
Map<String, String>[] maps = new Map[prefixes.length];
for( int i = 0; i < maps.length; i++ )
maps[i] = new HashMap<>();
// remove theme specific properties and remember only those for current theme
for( String key : themeSpecificKeys ) { for( String key : themeSpecificKeys ) {
String value = (String) properties.remove( key ); Object value = defaults.remove( key );
for( int i = 0; i < prefixes.length; i++ ) { for( String prefix : prefixes ) {
String prefix = prefixes[i];
if( key.startsWith( prefix ) ) { if( key.startsWith( prefix ) ) {
maps[i].put( key.substring( prefix.length() ), value ); themeSpecificDefaults.put( key.substring( prefix.length() ), value );
break; break;
} }
} }
} }
// copy values into single map (from lowest to highest priority) return themeSpecificDefaults;
Map<String, String> themeSpecificProps = new HashMap<>();
for( int i = maps.length - 1; i >= 0; i-- )
themeSpecificProps.putAll( maps[i] );
return themeSpecificProps;
} }
/** /**
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors * http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors
*/ */
private void loadNamedColors( Properties properties, Set<String> jsonUIKeys ) { private void loadNamedColors( UIDefaults defaults ) {
if( jsonColors == null ) if( colors == null )
return; return;
namedColors = new HashMap<>(); namedColors = new HashMap<>();
for( Map.Entry<String, String> e : jsonColors.entrySet() ) { for( Map.Entry<String, String> e : colors.entrySet() ) {
String value = e.getValue(); String value = e.getValue();
if( canParseColor( value ) ) { ColorUIResource color = parseColor( value );
if( color != null ) {
String key = e.getKey(); String key = e.getKey();
namedColors.put( key, value ); namedColors.put( key, color );
defaults.put( "ColorPalette." + key, color );
String uiKey = "ColorPalette." + key;
put( properties, uiKey, value );
// this is only necessary for copyIfSetInJson() (used for accent color)
jsonUIKeys.add( uiKey );
} }
} }
} }
@@ -385,7 +380,7 @@ public class IntelliJTheme
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors * http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors
*/ */
@SuppressWarnings( "unchecked" ) @SuppressWarnings( "unchecked" )
private void apply( String key, Object value, Properties properties, Set<String> jsonUIKeys ) { private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
if( value instanceof Map ) { if( value instanceof Map ) {
Map<String, Object> map = (Map<String, Object>)value; Map<String, Object> map = (Map<String, Object>)value;
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) { if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
@@ -393,12 +388,12 @@ public class IntelliJTheme
: SystemInfo.isMacOS ? "os.mac" : SystemInfo.isMacOS ? "os.mac"
: SystemInfo.isLinux ? "os.linux" : null; : SystemInfo.isLinux ? "os.linux" : null;
if( osKey != null && map.containsKey( osKey ) ) if( osKey != null && map.containsKey( osKey ) )
apply( key, map.get( osKey ), properties, jsonUIKeys ); apply( key, map.get( osKey ), defaults, defaultsKeysCache, uiKeys );
else if( map.containsKey( "os.default" ) ) else if( map.containsKey( "os.default" ) )
apply( key, map.get( "os.default" ), properties, jsonUIKeys ); apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys );
} else { } else {
for( Map.Entry<String, Object> e : map.entrySet() ) for( Map.Entry<String, Object> e : map.entrySet() )
apply( key + '.' + e.getKey(), e.getValue(), properties, jsonUIKeys ); apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
} }
} else { } else {
if( "".equals( value ) ) if( "".equals( value ) )
@@ -413,40 +408,25 @@ public class IntelliJTheme
key.equals( "Tree.rightChildIndent" ) ) key.equals( "Tree.rightChildIndent" ) )
return; // ignore return; // ignore
// ignore icons
if( key.endsWith( "Icon" ) )
return; // ignore
// map keys // map keys
key = uiKeyMapping.getOrDefault( key, key ); key = uiKeyMapping.getOrDefault( key, key );
if( key.isEmpty() ) if( key.isEmpty() )
return; // ignore key return; // ignore key
// exclude properties (1st level) // exclude properties
int dot = key.indexOf( '.' ); int dot = key.indexOf( '.' );
if( dot > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot + 1 ) ) ) if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) )
return; return;
// exclude properties (2st level) if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) )
int dot2 = (dot > 0) ? key.indexOf( '.', dot + 1 ) : -1;
if( dot2 > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot2 + 1 ) ) )
return; return;
// exclude properties (contains) uiKeys.add( key );
for( String s : uiKeyExcludesContains ) {
if( key.contains( s ) )
return;
}
if( uiKeyDoNotOverride.contains( key ) && jsonUIKeys.contains( key ) ) String valueStr = value.toString();
return;
jsonUIKeys.add( key );
String valueStr = value.toString().trim();
// map named colors // map named colors
String uiValue = namedColors.get( valueStr ); Object uiValue = namedColors.get( valueStr );
// parse value // parse value
if( uiValue == null ) { if( uiValue == null ) {
@@ -465,62 +445,45 @@ public class IntelliJTheme
// parse value // parse value
try { try {
UIDefaultsLoader.parseValue( key, valueStr, null ); uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
uiValue = valueStr;
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
UIDefaultsLoader.logParseError( key, valueStr, ex, true ); UIDefaultsLoader.logParseError( key, valueStr, ex, false );
return; // ignore invalid value return; // ignore invalid value
} }
} }
// wildcards if( key.startsWith( "*." ) ) {
if( applyWildcard( properties, key, uiValue ) ) // wildcard
return;
put( properties, key, uiValue );
}
}
private boolean applyWildcard( Properties properties, String key, String value ) {
if( !key.startsWith( "*." ) )
return false;
String tail = key.substring( 1 ); String tail = key.substring( 1 );
// because we can not iterate over the properties keys while // because we can not iterate over the UI defaults keys while
// modifying properties in the same loop, we have to copy the keys // modifying UI defaults in the same loop, we have to copy the keys
String[] keys = properties.keySet().toArray( new String[properties.size()] ); if( defaultsKeysCache.size() != defaults.size() ) {
defaultsKeysCache.clear();
Enumeration<Object> e = defaults.keys();
while( e.hasMoreElements() )
defaultsKeysCache.add( e.nextElement() );
}
// replace all values in properties that match the wildcard key // replace all values in UI defaults that match the wildcard key
for( String k : keys ) { for( Object k : defaultsKeysCache ) {
if( k.startsWith( "*" ) || if( k.equals( "Desktop.background" ) ||
k.startsWith( "@" ) ||
k.startsWith( "HelpButton." ) ||
k.startsWith( "JX" ) ||
k.startsWith( "Jide" ) ||
k.startsWith( "ProgressBar.selection" ) ||
k.startsWith( "TitlePane." ) ||
k.startsWith( "ToggleButton.tab." ) ||
k.equals( "Desktop.background" ) ||
k.equals( "DesktopIcon.background" ) || k.equals( "DesktopIcon.background" ) ||
k.equals( "TabbedPane.focusColor" ) || k.equals( "TabbedPane.focusColor" ) )
k.endsWith( ".hoverBackground" ) ||
k.endsWith( ".pressedBackground" ) )
continue; continue;
if( k instanceof String ) {
// support replacing of mapped keys // support replacing of mapped keys
// (e.g. set ComboBox.buttonEditableBackground to *.background // (e.g. set ComboBox.buttonEditableBackground to *.background
// because it is mapped from ComboBox.ArrowButton.background) // because it is mapped from ComboBox.ArrowButton.background)
String km = uiKeyInverseMapping.getOrDefault( k, k ); String km = uiKeyInverseMapping.getOrDefault( k, (String) k );
if( km.endsWith( tail ) && !k.startsWith( "CheckBox.icon." ) ) if( km.endsWith( tail ) && !((String)k).startsWith( "CheckBox.icon." ) )
put( properties, k, value ); defaults.put( k, uiValue );
}
}
} else
defaults.put( key, uiValue );
} }
// Note: also add wildcards to properties and let UIDefaultsLoader
// process it on BasicLookAndFeel UI defaults
put( properties, key, value );
return true;
} }
private String fixColorIfValid( String newColorStr, String colorStr ) { private String fixColorIfValid( String newColorStr, String colorStr ) {
@@ -534,11 +497,11 @@ public class IntelliJTheme
} }
} }
private void applyIconsColorPalette( Properties properties ) { private void applyColorPalette( UIDefaults defaults ) {
if( jsonIcons == null ) if( icons == null )
return; return;
Object palette = jsonIcons.get( "ColorPalette" ); Object palette = icons.get( "ColorPalette" );
if( !(palette instanceof Map) ) if( !(palette instanceof Map) )
return; return;
@@ -547,48 +510,44 @@ public class IntelliJTheme
for( Map.Entry<String, Object> e : colorPalette.entrySet() ) { for( Map.Entry<String, Object> e : colorPalette.entrySet() ) {
String key = e.getKey(); String key = e.getKey();
Object value = e.getValue(); Object value = e.getValue();
if( key.startsWith( "Checkbox." ) || key.startsWith( "#" ) || !(value instanceof String) ) if( key.startsWith( "Checkbox." ) || !(value instanceof String) )
continue; continue;
if( dark ) if( dark )
key = StringUtils.removeTrailing( key, ".Dark" ); key = StringUtils.removeTrailing( key, ".Dark" );
String color = toColor( (String) value ); ColorUIResource color = toColor( (String) value );
if( color != null ) if( color != null )
put( properties, key, color ); defaults.put( key, color );
} }
} }
private String toColor( String value ) { private ColorUIResource toColor( String value ) {
if( value.startsWith( "##" ) )
value = fixColorIfValid( value.substring( 1 ), value );
// map named colors // map named colors
String color = namedColors.get( value ); ColorUIResource color = namedColors.get( value );
// parse color // parse color
return (color != null) ? color : (canParseColor( value ) ? value : null); return (color != null) ? color : parseColor( value );
} }
private boolean canParseColor( String value ) { private ColorUIResource parseColor( String value ) {
try { try {
return UIDefaultsLoader.parseColor( value ) != null; return UIDefaultsLoader.parseColor( value );
} catch( IllegalArgumentException ex ) { } catch( IllegalArgumentException ex ) {
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to parse color: '" + value + '\'', ex ); return null;
return false;
} }
} }
/** /**
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for * Because IDEA uses SVGs for check boxes and radio buttons, the colors for
* these two components are specified in "icons > ColorPalette". * these two components are specified in "icons > ColorPalette".
* FlatLaf uses vector icons and expects colors for the two components in properties. * FlatLaf uses vector icons and expects colors for the two components in UI defaults.
*/ */
private void applyCheckBoxColors( Properties properties ) { private void applyCheckBoxColors( UIDefaults defaults ) {
if( jsonIcons == null ) if( icons == null )
return; return;
Object palette = jsonIcons.get( "ColorPalette" ); Object palette = icons.get( "ColorPalette" );
if( !(palette instanceof Map) ) if( !(palette instanceof Map) )
return; return;
@@ -610,9 +569,9 @@ public class IntelliJTheme
if( !dark && newKey.startsWith( checkBoxIconPrefix ) ) if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) ); newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
String color = toColor( (String) value ); ColorUIResource color = toColor( (String) value );
if( color != null ) { if( color != null ) {
put( properties, newKey, color ); defaults.put( newKey, color );
String key2 = checkboxDuplicateColors.get( key + ".Dark"); String key2 = checkboxDuplicateColors.get( key + ".Dark");
if( key2 != null ) { if( key2 != null ) {
@@ -633,7 +592,7 @@ public class IntelliJTheme
String newKey2 = checkboxKeyMapping.get( key2 ); String newKey2 = checkboxKeyMapping.get( key2 );
if( newKey2 != null ) if( newKey2 != null )
put( properties, newKey2, color ); defaults.put( newKey2, color );
} }
} }
@@ -644,13 +603,13 @@ public class IntelliJTheme
// update hover, pressed and focused colors // update hover, pressed and focused colors
if( checkboxModified ) { if( checkboxModified ) {
// for non-filled checkbox/radiobutton used in dark themes // for non-filled checkbox/radiobutton used in dark themes
properties.remove( "CheckBox.icon.focusWidth" ); defaults.remove( "CheckBox.icon.focusWidth" );
put( properties, "CheckBox.icon.hoverBorderColor", properties.get( "CheckBox.icon.focusedBorderColor" ) ); defaults.put( "CheckBox.icon.hoverBorderColor", defaults.get( "CheckBox.icon.focusedBorderColor" ) );
// for filled checkbox/radiobutton used in light themes // for filled checkbox/radiobutton used in light themes
properties.remove( "CheckBox.icon[filled].focusWidth" ); defaults.remove( "CheckBox.icon[filled].focusWidth" );
put( properties, "CheckBox.icon[filled].hoverBorderColor", properties.get( "CheckBox.icon[filled].focusedBorderColor" ) ); defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
put( properties, "CheckBox.icon[filled].focusedSelectedBackground", properties.get( "CheckBox.icon[filled].selectedBackground" ) ); defaults.put( "CheckBox.icon[filled].focusedSelectedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) );
if( dark ) { if( dark ) {
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg, // IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
@@ -664,16 +623,22 @@ public class IntelliJTheme
"CheckBox.icon[filled].focusedSelectedBorderColor", "CheckBox.icon[filled].focusedSelectedBorderColor",
}; };
for( String key : focusedBorderColorKeys ) { for( String key : focusedBorderColorKeys ) {
Object color = properties.get( key ); Color color = defaults.getColor( key );
if( color != null ) if( color != null ) {
put( properties, key, "fade(" + color + ", 65%)" ); defaults.put( key, new ColorUIResource( new Color(
(color.getRGB() & 0xffffff) | 0xa6000000, true ) ) );
}
} }
} }
} }
} }
private static final Set<String> uiKeyExcludesStartsWith; private void copyIfNotSet( UIDefaults defaults, String destKey, String srcKey, Set<String> uiKeys ) {
private static final String[] uiKeyExcludesContains; if( !uiKeys.contains( destKey ) )
defaults.put( destKey, defaults.get( srcKey ) );
}
private static final Set<String> uiKeyExcludes;
private static final Set<String> uiKeyDoNotOverride; private static final Set<String> uiKeyDoNotOverride;
/** Rename UI default keys (key --> value). */ /** Rename UI default keys (key --> value). */
private static final Map<String, String> uiKeyMapping = new HashMap<>(); private static final Map<String, String> uiKeyMapping = new HashMap<>();
@@ -685,30 +650,29 @@ public class IntelliJTheme
static { static {
// IntelliJ UI properties that are not used in FlatLaf // IntelliJ UI properties that are not used in FlatLaf
uiKeyExcludesStartsWith = new HashSet<>( Arrays.asList( uiKeyExcludes = new HashSet<>( Arrays.asList(
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.", "ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
"AvailableMnemonic.", "AvailableMnemonic.",
"Badge.", "Banner.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.", "BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
"Canvas.", "CellEditor.", "Code.", "CodeWithMe.", "ColumnControlButton.", "CombinedDiff.", "ComboBoxButton.", "Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
"CompilationCharts.", "CompletionPopup.", "ComplexPopup.", "Content.", "ContextHelp.", "CurrentMnemonic.", "Counter.", "CurrentMnemonic.", "Counter.",
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
"DisclosureButton.", "DragAndDrop.",
"Editor.", "EditorGroupsTabs.", "EditorTabs.", "Editor.", "EditorGroupsTabs.", "EditorTabs.",
"FileColor.", "FindPopup.", "FlameGraph.", "Focus.", "FileColor.", "FlameGraph.", "Focus.",
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.", "Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
"HeaderColor.", "HelpTooltip.", "Hg.", "HeaderColor.", "HelpTooltip.", "Hg.",
"IconBadge.", "InformationHint.", "InlineBanner.", "InplaceRefactoringPopup.", "IconBadge.", "InformationHint.", "InplaceRefactoringPopup.",
"Lesson.", "LineProfiler.", "Link.", "LiveIndicator.", "Lesson.", "Link.", "LiveIndicator.",
"MainMenu.", "MainToolbar.", "MainWindow.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.", "MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.", "NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
"OnePixelDivider.", "OptionButton.", "Outline.", "OnePixelDivider.", "OptionButton.", "Outline.",
"ParameterInfo.", "PresentationAssistant.", "Plugins.", "Profiler.", "ProgressIcon.", "PsiViewer.", "ParameterInfo.", "Plugins.", "ProgressIcon.", "PsiViewer.",
"Resizable.", "Review.", "ReviewList.", "RunToolbar.", "RunWidget.", "ReviewList.", "RunWidget.",
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.", "ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.", "SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
"StatusBar.", "StripeToolbar.", "StatusBar.",
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.", "TrialWidget.", "Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
"UIDesigner.", "UnattendedHostStatus.", "UIDesigner.", "UnattendedHostStatus.",
"ValidationTooltip.", "VersionControl.", "ValidationTooltip.", "VersionControl.",
"WelcomeScreen.", "WelcomeScreen.",
@@ -719,24 +683,11 @@ public class IntelliJTheme
// possible typos in .theme.json files // possible typos in .theme.json files
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link." "Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
) ); ) );
uiKeyExcludesContains = new String[] {
".darcula."
};
uiKeyDoNotOverride = new HashSet<>( Arrays.asList( uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
"TabbedPane.selectedForeground" "TabbedPane.selectedForeground"
) ); ) );
// "*."
uiKeyMapping.put( "*.fontFace", "" ); // ignore (used in OnePauintxi themes)
uiKeyMapping.put( "*.fontSize", "" ); // ignore (used in OnePauintxi themes)
// Button
uiKeyMapping.put( "Button.minimumSize", "" ); // ignore (used in Material Theme UI Lite)
// CheckBox.iconSize
uiKeyMapping.put( "CheckBox.iconSize", "" ); // ignore (used in Rider themes)
// ComboBox // ComboBox
uiKeyMapping.put( "ComboBox.background", "" ); // ignore uiKeyMapping.put( "ComboBox.background", "" ); // ignore
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
@@ -745,17 +696,14 @@ public class IntelliJTheme
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" ); uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" ); uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" ); uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
uiKeyCopying.put( "ComboBox.buttonSeparatorColor", "Component.borderColor" );
uiKeyCopying.put( "ComboBox.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
// Component // Component
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" ); uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" ); uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" ); uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" ); uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
uiKeyMapping.put( "Component.inactiveSuccessFocusColor", "Component.success.borderColor" );
uiKeyMapping.put( "Component.successFocusColor", "Component.success.focusedBorderColor" );
// Label
uiKeyMapping.put( "Label.disabledForegroundColor", "" ); // ignore (used in Material Theme UI Lite)
// Link // Link
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" ); uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
@@ -763,7 +711,10 @@ public class IntelliJTheme
// Menu // Menu
uiKeyMapping.put( "Menu.border", "Menu.margin" ); uiKeyMapping.put( "Menu.border", "Menu.margin" );
uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" ); uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" );
uiKeyCopying.put( "CheckBoxMenuItem.margin", "MenuItem.margin" );
uiKeyCopying.put( "RadioButtonMenuItem.margin", "MenuItem.margin" );
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" ); uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
uiKeyCopying.put( "MenuItem.underlineSelectionColor", "TabbedPane.underlineColor" );
// IDEA uses List.selectionBackground also for menu selection // IDEA uses List.selectionBackground also for menu selection
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" ); uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
@@ -771,14 +722,13 @@ public class IntelliJTheme
uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" ); uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" );
uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" ); uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" );
// ProgressBar: IDEA uses ProgressBar.trackColor and ProgressBar.progressColor // ProgressBar
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" ); uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" );
uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" ); uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" );
uiKeyCopying.put( "ProgressBar.selectionForeground", "ProgressBar.background" );
// RadioButton uiKeyCopying.put( "ProgressBar.selectionBackground", "ProgressBar.foreground" );
uiKeyMapping.put( "RadioButton.iconSize", "" ); // ignore (used in Rider themes)
// ScrollBar // ScrollBar
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" ); uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
@@ -788,30 +738,34 @@ public class IntelliJTheme
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" ); uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
// Slider // Slider
uiKeyMapping.put( "Slider.buttonColor", "Slider.thumbColor" );
uiKeyMapping.put( "Slider.buttonBorderColor", "" ); // ignore
uiKeyMapping.put( "Slider.thumb", "" ); // ignore (used in Material Theme UI Lite)
uiKeyMapping.put( "Slider.track", "" ); // ignore (used in Material Theme UI Lite)
uiKeyMapping.put( "Slider.trackDisabled", "" ); // ignore (used in Material Theme UI Lite)
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite) uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
uiKeyCopying.put( "Slider.trackValueColor", "ProgressBar.foreground" );
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
// Spinner
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
// TabbedPane // TabbedPane
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" ); uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" ); uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" ); uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
uiKeyMapping.put( "TabbedPane.tabAreaInsets", "" ); // ignore (used in Material Theme UI Lite)
// TableHeader
uiKeyMapping.put( "TableHeader.cellBorder", "" ); // ignore (used in Material Theme UI Lite)
uiKeyMapping.put( "TableHeader.height", "" ); // ignore (used in Material Theme UI Lite)
// TitlePane // TitlePane
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" ); uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" ); uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" );
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() ) for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
uiKeyInverseMapping.put( e.getValue(), e.getKey() ); uiKeyInverseMapping.put( e.getValue(), e.getKey() );
uiKeyCopying.put( "ToggleButton.tab.underlineColor", "TabbedPane.underlineColor" );
uiKeyCopying.put( "ToggleButton.tab.disabledUnderlineColor", "TabbedPane.disabledUnderlineColor" );
uiKeyCopying.put( "ToggleButton.tab.selectedBackground", "TabbedPane.selectedBackground" );
uiKeyCopying.put( "ToggleButton.tab.hoverBackground", "TabbedPane.hoverColor" );
uiKeyCopying.put( "ToggleButton.tab.focusBackground", "TabbedPane.focusColor" );
checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" ); checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" );
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" ); checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" ); checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
@@ -864,15 +818,17 @@ public class IntelliJTheme
} }
@Override @Override
void applyAdditionalProperties( Properties properties ) { void applyAdditionalDefaults( UIDefaults defaults ) {
theme.applyProperties( properties ); theme.applyProperties( defaults );
} }
@Override @Override
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() { protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
ArrayList<Class<?>> lafClasses = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() ); ArrayList<Class<?>> lafClasses = new ArrayList<>();
lafClasses.add( 1, theme.dark ? FlatDarkLaf.class : FlatLightLaf.class ); lafClasses.add( FlatLaf.class );
lafClasses.add( 2, theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class ); lafClasses.add( theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
lafClasses.add( theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
lafClasses.add( ThemeLaf.class );
return lafClasses; return lafClasses;
} }
} }

View File

@@ -70,8 +70,6 @@ class LinuxPopupMenuCanceler
} }
private void addWindowListeners( MenuElement selected ) { private void addWindowListeners( MenuElement selected ) {
removeWindowListeners();
// see BasicPopupMenuUI.MouseGrabber.grabWindow() // see BasicPopupMenuUI.MouseGrabber.grabWindow()
Component invoker = selected.getComponent(); Component invoker = selected.getComponent();
if( invoker instanceof JPopupMenu ) if( invoker instanceof JPopupMenu )

View File

@@ -41,8 +41,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
@@ -63,6 +61,7 @@ import com.formdev.flatlaf.util.HSLColor;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.SoftCache; import com.formdev.flatlaf.util.SoftCache;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
/** /**
@@ -86,14 +85,15 @@ class UIDefaultsLoader
private static final String WILDCARD_PREFIX = "*."; private static final String WILDCARD_PREFIX = "*.";
static final String KEY_VARIABLES = "FlatLaf.internal.variables"; static final String KEY_VARIABLES = "FlatLaf.internal.variables";
static final String KEY_PROPERTIES = "FlatLaf.internal.properties";
private static int parseColorDepth; private static int parseColorDepth;
private static Map<String, ColorUIResource> systemColorCache; private static Map<String, ColorUIResource> systemColorCache;
private static final SoftCache<String, Object> fontCache = new SoftCache<>(); private static final SoftCache<String, Object> fontCache = new SoftCache<>();
static ArrayList<Class<?>> getLafClassesForDefaultsLoading( Class<?> lookAndFeelClass ) { static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
Properties additionalDefaults, boolean dark, UIDefaults defaults )
{
// determine classes in class hierarchy in reverse order // determine classes in class hierarchy in reverse order
ArrayList<Class<?>> lafClasses = new ArrayList<>(); ArrayList<Class<?>> lafClasses = new ArrayList<>();
for( Class<?> lafClass = lookAndFeelClass; for( Class<?> lafClass = lookAndFeelClass;
@@ -102,54 +102,20 @@ class UIDefaultsLoader
{ {
lafClasses.add( 0, lafClass ); lafClasses.add( 0, lafClass );
} }
return lafClasses;
}
static Properties newUIProperties( boolean dark ) { loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults );
// UI key prefixes
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( dark );
Set<String> platformPrefixes = FlatLaf.getUIKeyPlatformPrefixes();
Set<String> specialPrefixes = FlatLaf.getUIKeySpecialPrefixes();
return new Properties() {
@Override
public synchronized Object put( Object k, Object value ) {
// process key prefixes (while loading properties files)
String key = (String) k;
while( key.startsWith( "[" ) ) {
int closeIndex = key.indexOf( ']' );
if( closeIndex < 0 )
return null; // ignore property with invalid prefix
String prefix = key.substring( 0, closeIndex + 1 );
if( specialPrefixes.contains( prefix ) )
break; // keep special prefix
if( !lightOrDarkPrefix.equals( prefix ) && !platformPrefixes.contains( prefix ) )
return null; // ignore property
// prefix is known and enabled --> remove prefix
key = key.substring( closeIndex + 1 );
}
return super.put( key, value );
}
};
} }
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons, static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
Consumer<Properties> intellijThemesHook, Properties additionalDefaults, boolean dark, UIDefaults defaults ) Properties additionalDefaults, boolean dark, UIDefaults defaults )
{ {
try { try {
// temporary cache system colors while loading defaults, // temporary cache system colors while loading defaults,
// which avoids that system color getter is invoked multiple times // which avoids that system color getter is invoked multiple times
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null; systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
// all properties files will be loaded into this map
Properties properties = newUIProperties( dark );
// load core properties files // load core properties files
Properties properties = new Properties();
for( Class<?> lafClass : lafClasses ) { for( Class<?> lafClass : lafClasses ) {
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties"; String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) { try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
@@ -176,10 +142,6 @@ class UIDefaultsLoader
addonClassLoaders.add( addonClassLoader ); addonClassLoaders.add( addonClassLoader );
} }
// apply IntelliJ themes properties
if( intellijThemesHook != null )
intellijThemesHook.accept( properties );
// load custom properties files (usually provided by applications) // load custom properties files (usually provided by applications)
List<Object> customDefaultsSources = FlatLaf.getCustomDefaultsSources(); List<Object> customDefaultsSources = FlatLaf.getCustomDefaultsSources();
int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0; int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0;
@@ -236,6 +198,41 @@ class UIDefaultsLoader
if( additionalDefaults != null ) if( additionalDefaults != null )
properties.putAll( additionalDefaults ); properties.putAll( additionalDefaults );
// collect all platform specific keys (but do not modify properties)
ArrayList<String> platformSpecificKeys = new ArrayList<>();
for( Object okey : properties.keySet() ) {
String key = (String) okey;
if( key.startsWith( "[" ) &&
(key.startsWith( "[win]" ) ||
key.startsWith( "[mac]" ) ||
key.startsWith( "[linux]" ) ||
key.startsWith( "[light]" ) ||
key.startsWith( "[dark]" )) )
platformSpecificKeys.add( key );
}
// remove platform specific properties and re-add only properties
// for current platform, but with platform prefix removed
if( !platformSpecificKeys.isEmpty() ) {
// handle light/dark specific properties
String lightOrDarkPrefix = dark ? "[dark]" : "[light]";
for( String key : platformSpecificKeys ) {
if( key.startsWith( lightOrDarkPrefix ) )
properties.put( key.substring( lightOrDarkPrefix.length() ), properties.remove( key ) );
}
// handle platform specific properties
String platformPrefix =
SystemInfo.isWindows ? "[win]" :
SystemInfo.isMacOS ? "[mac]" :
SystemInfo.isLinux ? "[linux]" : "[unknown]";
for( String key : platformSpecificKeys ) {
Object value = properties.remove( key );
if( key.startsWith( platformPrefix ) )
properties.put( key.substring( platformPrefix.length() ), value );
}
}
// get (and remove) wildcard replacements, which override all other defaults that end with same suffix // get (and remove) wildcard replacements, which override all other defaults that end with same suffix
HashMap<String, String> wildcards = new HashMap<>(); HashMap<String, String> wildcards = new HashMap<>();
Iterator<Entry<Object, Object>> it = properties.entrySet().iterator(); Iterator<Entry<Object, Object>> it = properties.entrySet().iterator();
@@ -290,15 +287,6 @@ class UIDefaultsLoader
// remember variables in defaults to allow using them in styles // remember variables in defaults to allow using them in styles
defaults.put( KEY_VARIABLES, variables ); defaults.put( KEY_VARIABLES, variables );
// remember properties (for testing)
if( FlatSystemProperties.getBoolean( KEY_PROPERTIES, false ) ) {
Properties properties2 = new Properties();
properties2.putAll( properties );
for( Map.Entry<String, String> e : wildcards.entrySet() )
properties2.put( WILDCARD_PREFIX + e.getKey(), e.getValue() );
defaults.put( KEY_PROPERTIES, properties2 );
}
// clear/disable system color cache // clear/disable system color cache
systemColorCache = null; systemColorCache = null;
} catch( IOException ex ) { } catch( IOException ex ) {
@@ -649,7 +637,6 @@ class UIDefaultsLoader
if( value.indexOf( ',' ) >= 0 ) { if( value.indexOf( ',' ) >= 0 ) {
// Syntax: top,left,bottom,right[,lineColor[,lineThickness[,arc]]] // Syntax: top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
List<String> parts = splitFunctionParams( value, ',' ); List<String> parts = splitFunctionParams( value, ',' );
try {
Insets insets = parseInsets( value ); Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() >= 5 && !parts.get( 4 ).isEmpty()) ColorUIResource lineColor = (parts.size() >= 5 && !parts.get( 4 ).isEmpty())
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver ) ? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver )
@@ -666,9 +653,6 @@ class UIDefaultsLoader
? new FlatLineBorder( insets, lineColor, lineThickness, arc ) ? new FlatLineBorder( insets, lineColor, lineThickness, arc )
: new FlatEmptyBorder( insets ); : new FlatEmptyBorder( insets );
}; };
} catch( RuntimeException ex ) {
throw new IllegalArgumentException( "invalid border '" + value + "' (" + ex.getMessage() + ")" );
}
} else } else
return parseInstance( value, resolver, addonClassLoaders ); return parseInstance( value, resolver, addonClassLoaders );
} }
@@ -739,7 +723,7 @@ class UIDefaultsLoader
Integer.parseInt( numbers.get( 1 ) ), Integer.parseInt( numbers.get( 1 ) ),
Integer.parseInt( numbers.get( 2 ) ), Integer.parseInt( numbers.get( 2 ) ),
Integer.parseInt( numbers.get( 3 ) ) ); Integer.parseInt( numbers.get( 3 ) ) );
} catch( NumberFormatException | IndexOutOfBoundsException ex ) { } catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid insets '" + value + "'" ); throw new IllegalArgumentException( "invalid insets '" + value + "'" );
} }
} }
@@ -752,7 +736,7 @@ class UIDefaultsLoader
return new DimensionUIResource( return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ), Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ) ); Integer.parseInt( numbers.get( 1 ) ) );
} catch( NumberFormatException | IndexOutOfBoundsException ex ) { } catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid size '" + value + "'" ); throw new IllegalArgumentException( "invalid size '" + value + "'" );
} }
} }
@@ -846,7 +830,6 @@ class UIDefaultsLoader
try { try {
switch( function ) { switch( function ) {
case "if": return parseColorIf( value, params, resolver ); case "if": return parseColorIf( value, params, resolver );
case "lazy": return parseColorLazy( value, params, resolver );
case "systemColor": return parseColorSystemColor( value, params, resolver ); case "systemColor": return parseColorSystemColor( value, params, resolver );
case "rgb": return parseColorRgbOrRgba( false, params, resolver ); case "rgb": return parseColorRgbOrRgba( false, params, resolver );
case "rgba": return parseColorRgbOrRgba( true, params, resolver ); case "rgba": return parseColorRgbOrRgba( true, params, resolver );
@@ -894,32 +877,6 @@ class UIDefaultsLoader
return parseColorOrFunction( resolver.apply( ifValue ), resolver ); return parseColorOrFunction( resolver.apply( ifValue ), resolver );
} }
/**
* Syntax: lazy(uiKey)
* <p>
* This "lazy" function is only used if the "lazy" is passed as parameter to another
* color function. Otherwise, the general "lazy" function is used.
* <p>
* Note: The color is resolved immediately, not lazy, because it is passed as parameter to another color function.
* So e.g. {@code darken(lazy(List.background), 10%)} is the same as {@code darken($List.background, 10%)}.
* <p>
* Only useful if a property is defined as lazy and that property is used
* in another property's color function. E.g.
*
* <pre>{@code
* someProperty = lazy(List.background)
* anotherProperty = darken($someProperty, 10%)
* }</pre>
*/
private static Object parseColorLazy( String value, List<String> params, Function<String, String> resolver )
throws IllegalArgumentException
{
if( params.size() != 1 )
throw newMissingParametersException( value );
return parseColorOrFunction( resolver.apply( PROPERTY_PREFIX + params.get( 0 ) ), resolver );
}
/** /**
* Syntax: systemColor(name[,defaultValue]) * Syntax: systemColor(name[,defaultValue])
* - name: system color name * - name: system color name
@@ -1017,7 +974,7 @@ class UIDefaultsLoader
* fadein(color,amount[,options]) or fadeout(color,amount[,options]) * fadein(color,amount[,options]) or fadeout(color,amount[,options])
* - color: a color (e.g. #f00) or a color function * - color: a color (e.g. #f00) or a color function
* - amount: percentage 0-100% * - amount: percentage 0-100%
* - options: [relative] [autoInverse] [noAutoInverse] [derived] [lazy] * - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
*/ */
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase, private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
List<String> params, Function<String, String> resolver ) List<String> params, Function<String, String> resolver )
@@ -1027,15 +984,15 @@ class UIDefaultsLoader
int amount = parsePercentage( params.get( 1 ) ); int amount = parsePercentage( params.get( 1 ) );
boolean relative = false; boolean relative = false;
boolean autoInverse = false; boolean autoInverse = false;
boolean derived = false;
boolean lazy = false; boolean lazy = false;
boolean derived = false;
if( params.size() > 2 ) { if( params.size() > 2 ) {
String options = params.get( 2 ); String options = params.get( 2 );
relative = options.contains( "relative" ); relative = options.contains( "relative" );
autoInverse = options.contains( "autoInverse" ); autoInverse = options.contains( "autoInverse" );
derived = options.contains( "derived" );
lazy = options.contains( "lazy" ); lazy = options.contains( "lazy" );
derived = options.contains( "derived" );
// use autoInverse by default for derived colors, except if noAutoInverse is set // use autoInverse by default for derived colors, except if noAutoInverse is set
if( derived && !options.contains( "noAutoInverse" ) ) if( derived && !options.contains( "noAutoInverse" ) )
@@ -1046,8 +1003,14 @@ class UIDefaultsLoader
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( ColorFunction function = new ColorFunctions.HSLIncreaseDecrease(
hslIndex, increase, amount, relative, autoInverse ); hslIndex, increase, amount, relative, autoInverse );
if( lazy ) if( lazy ) {
return newLazyColorFunction( colorStr, function ); return (LazyValue) t -> {
Object color = lazyUIManagerGet( colorStr );
return (color instanceof Color)
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
: null;
};
}
// parse base color, apply function and create derived color // parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver ); return parseFunctionBaseColor( colorStr, function, derived, resolver );
@@ -1076,8 +1039,14 @@ class UIDefaultsLoader
// create function // create function
ColorFunction function = new ColorFunctions.Fade( amount ); ColorFunction function = new ColorFunctions.Fade( amount );
if( lazy ) if( lazy ) {
return newLazyColorFunction( colorStr, function ); return (LazyValue) t -> {
Object color = lazyUIManagerGet( colorStr );
return (color instanceof Color)
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
: null;
};
}
// parse base color, apply function and create derived color // parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver ); return parseFunctionBaseColor( colorStr, function, derived, resolver );
@@ -1087,7 +1056,7 @@ class UIDefaultsLoader
* Syntax: spin(color,angle[,options]) * Syntax: spin(color,angle[,options])
* - color: a color (e.g. #f00) or a color function * - color: a color (e.g. #f00) or a color function
* - angle: number of degrees to rotate * - angle: number of degrees to rotate
* - options: [derived] [lazy] * - options: [derived]
*/ */
private static Object parseColorSpin( List<String> params, Function<String, String> resolver ) private static Object parseColorSpin( List<String> params, Function<String, String> resolver )
throws IllegalArgumentException throws IllegalArgumentException
@@ -1095,20 +1064,15 @@ class UIDefaultsLoader
String colorStr = params.get( 0 ); String colorStr = params.get( 0 );
int amount = parseInteger( params.get( 1 ) ); int amount = parseInteger( params.get( 1 ) );
boolean derived = false; boolean derived = false;
boolean lazy = false;
if( params.size() > 2 ) { if( params.size() > 2 ) {
String options = params.get( 2 ); String options = params.get( 2 );
derived = options.contains( "derived" ); derived = options.contains( "derived" );
lazy = options.contains( "lazy" );
} }
// create function // create function
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false ); ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
if( lazy )
return newLazyColorFunction( colorStr, function );
// parse base color, apply function and create derived color // parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver ); return parseFunctionBaseColor( colorStr, function, derived, resolver );
} }
@@ -1120,7 +1084,7 @@ class UIDefaultsLoader
* changeAlpha(color,value[,options]) * changeAlpha(color,value[,options])
* - color: a color (e.g. #f00) or a color function * - color: a color (e.g. #f00) or a color function
* - value: for hue: number of degrees; otherwise: percentage 0-100% * - value: for hue: number of degrees; otherwise: percentage 0-100%
* - options: [derived] [lazy] * - options: [derived]
*/ */
private static Object parseColorChange( int hslIndex, private static Object parseColorChange( int hslIndex,
List<String> params, Function<String, String> resolver ) List<String> params, Function<String, String> resolver )
@@ -1131,33 +1095,27 @@ class UIDefaultsLoader
? parseInteger( params.get( 1 ) ) ? parseInteger( params.get( 1 ) )
: parsePercentage( params.get( 1 ) ); : parsePercentage( params.get( 1 ) );
boolean derived = false; boolean derived = false;
boolean lazy = false;
if( params.size() > 2 ) { if( params.size() > 2 ) {
String options = params.get( 2 ); String options = params.get( 2 );
derived = options.contains( "derived" ); derived = options.contains( "derived" );
lazy = options.contains( "lazy" );
} }
// create function // create function
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value ); ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
if( lazy )
return newLazyColorFunction( colorStr, function );
// parse base color, apply function and create derived color // parse base color, apply function and create derived color
return parseFunctionBaseColor( colorStr, function, derived, resolver ); return parseFunctionBaseColor( colorStr, function, derived, resolver );
} }
/** /**
* Syntax: mix(color1,color2[,weight][,options]) or * Syntax: mix(color1,color2[,weight]) or
* tint(color[,weight][,options]) or * tint(color[,weight]) or
* shade(color[,weight][,options]) * shade(color[,weight])
* - color1: a color (e.g. #f00) or a color function * - color1: a color (e.g. #f00) or a color function
* - color2: a color (e.g. #f00) or a color function * - color2: a color (e.g. #f00) or a color function
* - weight: the weight (in range 0-100%) to mix the two colors * - weight: the weight (in range 0-100%) to mix the two colors
* larger weight uses more of first color, smaller weight more of second color * larger weight uses more of first color, smaller weight more of second color
* - options: [derived] [lazy]
*/ */
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver ) private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver )
throws IllegalArgumentException throws IllegalArgumentException
@@ -1166,36 +1124,18 @@ class UIDefaultsLoader
if( color1Str == null ) if( color1Str == null )
color1Str = params.get( i++ ); color1Str = params.get( i++ );
String color2Str = params.get( i++ ); String color2Str = params.get( i++ );
int weight = 50; int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
boolean derived = false;
boolean lazy = false;
if( params.size() > i ) {
String weightStr = params.get( i );
if( !weightStr.isEmpty() && Character.isDigit( weightStr.charAt( 0 ) ) ) {
weight = parsePercentage( weightStr );
i++;
}
}
if( params.size() > i ) {
String options = params.get( i );
derived = options.contains( "derived" );
lazy = options.contains( "lazy" );
}
// parse second color // parse second color
ColorUIResource color1 = (ColorUIResource) parseColorOrFunction( resolver.apply( color1Str ), resolver ); ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver );
if( color1 == null ) if( color2 == null )
return null; return null;
// create function // create function
ColorFunction function = new ColorFunctions.Mix2( color1, weight ); ColorFunction function = new ColorFunctions.Mix( color2, weight );
if( lazy )
return newLazyColorFunction( color2Str, function );
// parse first color, apply function and create mixed color // parse first color, apply function and create mixed color
return parseFunctionBaseColor( color2Str, function, derived, resolver ); return parseFunctionBaseColor( color1Str, function, false, resolver );
} }
/** /**
@@ -1289,15 +1229,6 @@ class UIDefaultsLoader
return new ColorUIResource( newColor ); return new ColorUIResource( newColor );
} }
private static LazyValue newLazyColorFunction( String uiKey, ColorFunction function ) {
return (LazyValue) t -> {
Object color = lazyUIManagerGet( uiKey );
return (color instanceof Color)
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
: null;
};
}
/** /**
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey] * Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
*/ */
@@ -1383,17 +1314,17 @@ class UIDefaultsLoader
break; break;
} }
} }
} catch( RuntimeException | IOException ex ) { } catch( IOException ex ) {
throw new IllegalArgumentException( "invalid font '" + value + "' (" + ex.getMessage() + ")" ); throw new IllegalArgumentException( ex );
} }
if( style != -1 && styleChange != 0 ) if( style != -1 && styleChange != 0 )
throw new IllegalArgumentException( "invalid font '" + value + "': can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic')" ); throw new IllegalArgumentException( "can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic') in '" + value + "'" );
if( styleChange != 0 ) { if( styleChange != 0 ) {
if( (styleChange & Font.BOLD) != 0 && (styleChange & (Font.BOLD << 16)) != 0 ) if( (styleChange & Font.BOLD) != 0 && (styleChange & (Font.BOLD << 16)) != 0 )
throw new IllegalArgumentException( "invalid font '" + value + "': can not use '+bold' and '-bold'" ); throw new IllegalArgumentException( "can not use '+bold' and '-bold' in '" + value + "'" );
if( (styleChange & Font.ITALIC) != 0 && (styleChange & (Font.ITALIC << 16)) != 0 ) if( (styleChange & Font.ITALIC) != 0 && (styleChange & (Font.ITALIC << 16)) != 0 )
throw new IllegalArgumentException( "invalid font '" + value + "': can not use '+italic' and '-italic'" ); throw new IllegalArgumentException( "can not use '+italic' and '-italic' in '" + value + "'" );
} }
font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize ); font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize );
@@ -1533,7 +1464,7 @@ class UIDefaultsLoader
return (LazyValue) t -> { return (LazyValue) t -> {
return new GrayFilter( brightness, contrast, alpha ); return new GrayFilter( brightness, contrast, alpha );
}; };
} catch( NumberFormatException | IndexOutOfBoundsException ex ) { } catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid gray filter '" + value + "'" ); throw new IllegalArgumentException( "invalid gray filter '" + value + "'" );
} }
} }

View File

@@ -18,95 +18,44 @@ package com.formdev.flatlaf.icons;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Insets; import java.awt.RenderingHints;
import java.awt.Window;
import javax.swing.SwingUtilities;
import com.formdev.flatlaf.ui.FlatButtonUI; import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatTitlePane;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.UIScale;
/** /**
* Base class for window icons. * Base class for window icons.
* *
* @uiDefault TitlePane.buttonSize Dimension * @uiDefault TitlePane.buttonSize Dimension
* @uiDefault TitlePane.buttonInsets Insets optional
* @uiDefault TitlePane.buttonArc int optional
* @uiDefault TitlePane.buttonSymbolHeight int * @uiDefault TitlePane.buttonSymbolHeight int
* @uiDefault TitlePane.buttonBackground Color optional * @uiDefault TitlePane.buttonHoverBackground Color
* @uiDefault TitlePane.buttonForeground Color optional * @uiDefault TitlePane.buttonPressedBackground Color
* @uiDefault TitlePane.buttonInactiveBackground Color optional
* @uiDefault TitlePane.buttonInactiveForeground Color optional
* @uiDefault TitlePane.buttonHoverBackground Color optional
* @uiDefault TitlePane.buttonHoverForeground Color optional
* @uiDefault TitlePane.buttonPressedBackground Color optional
* @uiDefault TitlePane.buttonPressedForeground Color optional
* *
* @author Karl Tauber * @author Karl Tauber
*/ */
public abstract class FlatWindowAbstractIcon public abstract class FlatWindowAbstractIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
/** @since 3.6 */ protected final Insets insets; private final int symbolHeight;
/** @since 3.6 */ protected final int arc; private final Color hoverBackground;
/** @since 3.6 */ protected final int symbolHeight; private final Color pressedBackground;
/** @since 3.6 */ protected final Color background;
/** @since 3.6 */ protected final Color foreground;
/** @since 3.6 */ protected final Color inactiveBackground;
/** @since 3.6 */ protected final Color inactiveForeground;
protected final Color hoverBackground;
/** @since 3.6 */ protected final Color hoverForeground;
protected final Color pressedBackground;
/** @since 3.6 */ protected final Color pressedForeground;
/** @since 3.2 */ /** @since 3.2 */
protected FlatWindowAbstractIcon( String windowStyle ) { protected FlatWindowAbstractIcon( String windowStyle ) {
this( windowStyle, null, null, null, null, null, null, null, null );
}
/** @since 3.6 */
protected FlatWindowAbstractIcon( String windowStyle,
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
{
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ), this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
FlatUIUtils.getSubUIInsets( "TitlePane.buttonInsets", windowStyle ),
FlatUIUtils.getSubUIInt( "TitlePane.buttonArc", windowStyle, 0 ),
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ), FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
(background != null) ? background : FlatUIUtils.getSubUIColor( "TitlePane.buttonBackground", windowStyle ), FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
(foreground != null) ? foreground : FlatUIUtils.getSubUIColor( "TitlePane.buttonForeground", windowStyle ), FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
(inactiveBackground != null) ? inactiveBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveBackground", windowStyle ),
(inactiveForeground != null) ? inactiveForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveForeground", windowStyle ),
(hoverBackground != null) ? hoverBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
(hoverForeground != null) ? hoverForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverForeground", windowStyle ),
(pressedBackground != null) ? pressedBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ),
(pressedForeground != null) ? pressedForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedForeground", windowStyle ) );
} }
/** @since 3.6 */ /** @since 3.2 */
protected FlatWindowAbstractIcon( Dimension size, Insets insets, int arc, int symbolHeight, protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
{
super( size.width, size.height, null ); super( size.width, size.height, null );
this.insets = (insets != null) ? insets : new Insets( 0, 0, 0, 0 );
this.arc = arc;
this.symbolHeight = symbolHeight; this.symbolHeight = symbolHeight;
this.background = background;
this.foreground = foreground;
this.inactiveBackground = inactiveBackground;
this.inactiveForeground = inactiveForeground;
this.hoverBackground = hoverBackground; this.hoverBackground = hoverBackground;
this.hoverForeground = hoverForeground;
this.pressedBackground = pressedBackground; this.pressedBackground = pressedBackground;
this.pressedForeground = pressedForeground;
} }
@Override @Override
@@ -120,39 +69,26 @@ public abstract class FlatWindowAbstractIcon
/** @since 3.5.2 */ /** @since 3.5.2 */
@Override @Override
protected void paintBackground( Component c, Graphics2D g, int x, int y ) { protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
Color bg = null; Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
if( background != null || inactiveBackground != null ) {
Window window = SwingUtilities.windowForComponent( c );
bg = (window == null || window.isActive()) ? background : inactiveBackground;
}
Color background = FlatButtonUI.buttonStateColor( c, bg, null, null, hoverBackground, pressedBackground );
if( background != null ) { if( background != null ) {
Insets insets = UIScale.scale( this.insets ); // disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%)
float arc = UIScale.scale( (float) this.arc ); Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
// derive color from title pane background // fill background of whole component
if( background instanceof DerivedColor ) { g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
Container titlePane = SwingUtilities.getAncestorOfClass( FlatTitlePane.class, c ); g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
Component baseComp = (titlePane != null) ? titlePane : c;
background = FlatUIUtils.deriveColor( background, baseComp.getBackground() );
}
g.setColor( background ); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
FlatUIUtils.paintComponentBackground( g, insets.left, insets.top,
c.getWidth() - insets.left - insets.right,
c.getHeight() - insets.top - insets.bottom,
0, arc );
} }
} }
protected Color getForeground( Component c ) { protected Color getForeground( Component c ) {
Color fg = null; return c.getForeground();
if( foreground != null || inactiveForeground != null ) {
Window window = SwingUtilities.windowForComponent( c );
fg = (window == null || window.isActive()) ? foreground : inactiveForeground;
} }
return FlatButtonUI.buttonStateColor( c, (fg != null) ? fg : c.getForeground(),
null, null, hoverForeground, pressedForeground ); /** @since 3.2 */
protected int getSymbolHeight() {
return symbolHeight;
} }
} }

View File

@@ -17,54 +17,53 @@
package com.formdev.flatlaf.icons; package com.formdev.flatlaf.icons;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
/** /**
* "close" icon for windows (frames and dialogs). * "close" icon for windows (frames and dialogs).
* *
* @uiDefault TitlePane.closeBackground Color optional * @uiDefault TitlePane.closeHoverBackground Color
* @uiDefault TitlePane.closeForeground Color optional * @uiDefault TitlePane.closePressedBackground Color
* @uiDefault TitlePane.closeInactiveBackground Color optional * @uiDefault TitlePane.closeHoverForeground Color
* @uiDefault TitlePane.closeInactiveForeground Color optional * @uiDefault TitlePane.closePressedForeground Color
* @uiDefault TitlePane.closeHoverBackground Color optional
* @uiDefault TitlePane.closeHoverForeground Color optional
* @uiDefault TitlePane.closePressedBackground Color optional
* @uiDefault TitlePane.closePressedForeground Color optional
* *
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatWindowCloseIcon public class FlatWindowCloseIcon
extends FlatWindowAbstractIcon extends FlatWindowAbstractIcon
{ {
private final Color hoverForeground;
private final Color pressedForeground;
public FlatWindowCloseIcon() { public FlatWindowCloseIcon() {
this( null ); this( null );
} }
/** @since 3.2 */ /** @since 3.2 */
public FlatWindowCloseIcon( String windowStyle ) { public FlatWindowCloseIcon( String windowStyle ) {
super( windowStyle, super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closeBackground", windowStyle ), FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
FlatUIUtils.getSubUIColor( "TitlePane.closeForeground", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveBackground", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveForeground", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ), FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle ), FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ),
FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle ) ); hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
} }
@Override @Override
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
int iwh = (int) (symbolHeight * scaleFactor); int iwh = (int) (getSymbolHeight() * scaleFactor);
int ix = x + ((width - iwh) / 2); int ix = x + ((width - iwh) / 2);
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
int ix2 = ix + iwh - 1; int ix2 = ix + iwh - 1;
int iy2 = iy + iwh - 1; int iy2 = iy + iwh - 1;
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 ); Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
path.moveTo( ix, iy ); path.moveTo( ix, iy );
@@ -74,4 +73,9 @@ public class FlatWindowCloseIcon
g.setStroke( new BasicStroke( thickness ) ); g.setStroke( new BasicStroke( thickness ) );
g.draw( path ); g.draw( path );
} }
@Override
protected Color getForeground( Component c ) {
return FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground );
}
} }

View File

@@ -37,7 +37,7 @@ public class FlatWindowIconifyIcon
@Override @Override
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
int iw = (int) (symbolHeight * scaleFactor); int iw = (int) (getSymbolHeight() * scaleFactor);
int ih = Math.max( (int) scaleFactor, 1 ); int ih = Math.max( (int) scaleFactor, 1 );
int ix = x + ((width - iw) / 2); int ix = x + ((width - iw) / 2);
int iy = y + ((height - ih) / 2); int iy = y + ((height - ih) / 2);

View File

@@ -39,11 +39,10 @@ public class FlatWindowMaximizeIcon
@Override @Override
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
int iwh = (int) (symbolHeight * scaleFactor); int iwh = (int) (getSymbolHeight() * scaleFactor);
int ix = x + ((width - iwh) / 2); int ix = x + ((width - iwh) / 2);
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
int arc = Math.max( (int) (1.5 * scaleFactor), 2 ); int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
g.fill( SystemInfo.isWindows_11_orLater g.fill( SystemInfo.isWindows_11_orLater

View File

@@ -42,15 +42,14 @@ public class FlatWindowRestoreIcon
@Override @Override
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
int iwh = (int) (symbolHeight * scaleFactor); int iwh = (int) (getSymbolHeight() * scaleFactor);
int ix = x + ((width - iwh) / 2); int ix = x + ((width - iwh) / 2);
int iy = y + ((height - iwh) / 2); int iy = y + ((height - iwh) / 2);
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater; float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
int arc = Math.max( (int) (1.5 * scaleFactor), 2 ); int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
int arcOuter = (int) (arc + (1.5 * scaleFactor)); int arcOuter = (int) (arc + (1.5 * scaleFactor));
int rwh = (int) ((symbolHeight - 2) * scaleFactor); int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
int ro2 = iwh - rwh; int ro2 = iwh - rwh;
// upper-right rectangle // upper-right rectangle

View File

@@ -59,8 +59,6 @@ import com.formdev.flatlaf.util.DerivedColor;
* @uiDefault Component.error.focusedBorderColor Color * @uiDefault Component.error.focusedBorderColor Color
* @uiDefault Component.warning.borderColor Color * @uiDefault Component.warning.borderColor Color
* @uiDefault Component.warning.focusedBorderColor Color * @uiDefault Component.warning.focusedBorderColor Color
* @uiDefault Component.success.borderColor Color
* @uiDefault Component.success.focusedBorderColor Color
* @uiDefault Component.custom.borderColor Color * @uiDefault Component.custom.borderColor Color
* *
* @author Karl Tauber * @author Karl Tauber
@@ -83,8 +81,6 @@ public class FlatBorder
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" ); @Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" ); @Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" ); @Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
/** @since 3.6 */ @Styleable(dot=true) protected Color successBorderColor = UIManager.getColor( "Component.success.borderColor" );
/** @since 3.6 */ @Styleable(dot=true) protected Color successFocusedBorderColor = UIManager.getColor( "Component.success.focusedBorderColor" );
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" ); @Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
// only used via styling (not in UI defaults, but has likewise client properties) // only used via styling (not in UI defaults, but has likewise client properties)
@@ -172,9 +168,6 @@ public class FlatBorder
case FlatClientProperties.OUTLINE_WARNING: case FlatClientProperties.OUTLINE_WARNING:
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor; return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
case FlatClientProperties.OUTLINE_SUCCESS:
return isFocused( c ) ? successFocusedBorderColor : successBorderColor;
} }
} else if( outline instanceof Color ) { } else if( outline instanceof Color ) {
Color color = (Color) outline; Color color = (Color) outline;

View File

@@ -280,6 +280,8 @@ public class FlatButtonUI
LookAndFeel.installProperty( b, "opaque", false ); LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) ); LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
MigLayoutVisualPadding.install( b );
} }
@Override @Override
@@ -289,21 +291,8 @@ public class FlatButtonUI
oldStyleValues = null; oldStyleValues = null;
borderShared = null; borderShared = null;
defaults_initialized = false;
}
@Override
protected void installListeners( AbstractButton b ) {
super.installListeners( b );
MigLayoutVisualPadding.install( b );
}
@Override
protected void uninstallListeners( AbstractButton b ) {
super.uninstallListeners( b );
MigLayoutVisualPadding.uninstall( b ); MigLayoutVisualPadding.uninstall( b );
defaults_initialized = false;
} }
@Override @Override
@@ -381,12 +370,6 @@ public class FlatButtonUI
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value ); return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
} }
// update internal values; otherwise isCustomBackground() and isCustomForeground() would return wrong results
switch( key ) {
case "background": background = (Color) value; break;
case "foreground": foreground = (Color) value; break;
}
if( "iconTextGap".equals( key ) && value instanceof Integer ) if( "iconTextGap".equals( key ) && value instanceof Integer )
value = UIScale.scale( (Integer) value ); value = UIScale.scale( (Integer) value );

View File

@@ -17,7 +17,6 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.Container;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@@ -25,9 +24,7 @@ import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.ActionMap; import javax.swing.ActionMap;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField; import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
@@ -36,7 +33,6 @@ import javax.swing.text.DefaultCaret;
import javax.swing.text.DefaultEditorKit; import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Document; import javax.swing.text.Document;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
import javax.swing.text.Utilities; import javax.swing.text.Utilities;
/** /**
@@ -52,15 +48,12 @@ public class FlatCaret
{ {
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo"; private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
// selectAllOnFocusPolicy
private static final int NEVER = 0, ONCE = 1, ALWAYS = 2;
private final String selectAllOnFocusPolicy; private final String selectAllOnFocusPolicy;
private final boolean selectAllOnMouseClick; private final boolean selectAllOnMouseClick;
private boolean inInstall; private boolean inInstall;
private boolean wasFocused; private boolean wasFocused;
private boolean wasFocusTemporaryLost; private boolean wasTemporaryLost;
private boolean isMousePressed; private boolean isMousePressed;
private boolean isWordSelection; private boolean isWordSelection;
private boolean isLineSelection; private boolean isLineSelection;
@@ -101,9 +94,6 @@ public class FlatCaret
// restore selection // restore selection
select( (int) ci[1], (int) ci[0] ); select( (int) ci[1], (int) ci[0] );
if( ci[4] != 0 )
wasFocused = true;
// if text component is focused, then caret and selection are visible, // if text component is focused, then caret and selection are visible,
// but when switching theme, the component does not yet have // but when switching theme, the component does not yet have
// a highlighter and the selection is not painted // a highlighter and the selection is not painted
@@ -131,7 +121,6 @@ public class FlatCaret
getMark(), getMark(),
getBlinkRate(), getBlinkRate(),
System.currentTimeMillis(), System.currentTimeMillis(),
wasFocused ? 1 : 0,
} ); } );
super.deinstall( c ); super.deinstall( c );
@@ -151,36 +140,11 @@ public class FlatCaret
super.adjustVisibility( nloc ); super.adjustVisibility( nloc );
} }
@Override
public void setDot( int dot ) {
super.setDot( dot );
// mark as focused if invoked from JTextComponent.setCaretPosition()
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
if( !wasFocused &&
getSelectAllOnFocusPolicy() == ONCE &&
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "setCaretPosition", 6 ) )
wasFocused = true;
}
@Override
public void moveDot( int dot ) {
super.moveDot( dot );
// mark as focused if invoked from JTextComponent.moveCaretPosition()
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
if( !wasFocused &&
getSelectAllOnFocusPolicy() == ONCE &&
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "moveCaretPosition", 6 ) )
wasFocused = true;
}
@Override @Override
public void focusGained( FocusEvent e ) { public void focusGained( FocusEvent e ) {
if( !inInstall && !wasFocusTemporaryLost && (!isMousePressed || isSelectAllOnMouseClick()) ) if( !inInstall && !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
selectAllOnFocusGained(); selectAllOnFocusGained();
wasTemporaryLost = false;
wasFocusTemporaryLost = false;
wasFocused = true; wasFocused = true;
super.focusGained( e ); super.focusGained( e );
@@ -188,7 +152,7 @@ public class FlatCaret
@Override @Override
public void focusLost( FocusEvent e ) { public void focusLost( FocusEvent e ) {
wasFocusTemporaryLost = e.isTemporary(); wasTemporaryLost = e.isTemporary();
super.focusLost( e ); super.focusLost( e );
} }
@@ -268,13 +232,24 @@ public class FlatCaret
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) ) if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
return; return;
int selectAllOnFocusPolicy = getSelectAllOnFocusPolicy(); Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
if( selectAllOnFocusPolicy == NEVER ) if( selectAllOnFocusPolicy == null )
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
return; return;
if( selectAllOnFocusPolicy == ONCE && !isMousePressed ) { if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
// policy is "once" (or null or unknown)
// was already focused? // was already focused?
if( wasFocused && !(c instanceof JFormattedTextField) ) if( wasFocused )
return;
// check whether selection was modified before gaining focus
int dot = getDot();
int mark = getMark();
if( dot != mark || dot != doc.getLength() )
return; return;
} }
@@ -290,51 +265,16 @@ public class FlatCaret
select( 0, c2.getDocument().getLength() ); select( 0, c2.getDocument().getLength() );
} ); } );
} else } else {
select( 0, doc.getLength() ); select( 0, doc.getLength() );
} }
}
private void select( int mark, int dot ) { private void select( int mark, int dot ) {
if( mark != getMark() ) if( mark != getMark() )
setDot( mark, Position.Bias.Forward ); setDot( mark );
if( dot != getDot() ) if( dot != getDot() )
moveDot( dot, Position.Bias.Forward ); moveDot( dot );
}
private int getSelectAllOnFocusPolicy() {
Object value = getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
// Note: using String.valueOf() because selectAllOnFocusPolicy may be null
switch( String.valueOf( value instanceof String ? value : selectAllOnFocusPolicy ) ) {
default:
case SELECT_ALL_ON_FOCUS_POLICY_NEVER: return NEVER;
case SELECT_ALL_ON_FOCUS_POLICY_ONCE: return ONCE;
case SELECT_ALL_ON_FOCUS_POLICY_ALWAYS: return ALWAYS;
}
}
private boolean isSelectAllOnMouseClick() {
Object value = getClientProperty( SELECT_ALL_ON_MOUSE_CLICK );
return (value instanceof Boolean) ? (boolean) value : selectAllOnMouseClick;
}
private Object getClientProperty( String key ) {
JTextComponent c = getComponent();
if( c == null )
return null;
Object value = c.getClientProperty( key );
if( value != null )
return value;
Container parent = c.getParent();
if( parent instanceof JComboBox )
return ((JComboBox<?>)parent).getClientProperty( key );
if( parent instanceof JSpinner.DefaultEditor ) {
parent = parent.getParent();
if( parent instanceof JSpinner )
return ((JSpinner)parent).getClientProperty( key );
}
return null;
} }
/** @since 1.4 */ /** @since 1.4 */

View File

@@ -225,8 +225,6 @@ public class FlatComboBoxUI
} }
}; };
comboBox.addMouseListener( hoverListener ); comboBox.addMouseListener( hoverListener );
MigLayoutVisualPadding.install( comboBox );
} }
@Override @Override
@@ -235,8 +233,6 @@ public class FlatComboBoxUI
comboBox.removeMouseListener( hoverListener ); comboBox.removeMouseListener( hoverListener );
hoverListener = null; hoverListener = null;
MigLayoutVisualPadding.uninstall( comboBox );
} }
@Override @Override
@@ -278,6 +274,8 @@ public class FlatComboBoxUI
comboBox.setMaximumRowCount( maximumRowCount ); comboBox.setMaximumRowCount( maximumRowCount );
paddingBorder = new CellPaddingBorder( padding ); paddingBorder = new CellPaddingBorder( padding );
MigLayoutVisualPadding.install( comboBox );
} }
@Override @Override
@@ -306,6 +304,8 @@ public class FlatComboBoxUI
oldStyleValues = null; oldStyleValues = null;
borderShared = null; borderShared = null;
MigLayoutVisualPadding.uninstall( comboBox );
} }
@Override @Override
@@ -882,7 +882,7 @@ public class FlatComboBoxUI
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration(); GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
if( gc != null ) { if( gc != null ) {
Rectangle screenBounds = gc.getBounds(); Rectangle screenBounds = gc.getBounds();
Insets screenInsets = FlatUIUtils.getScreenInsets( gc ); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
displayWidth = Math.min( displayWidth, screenBounds.width - screenInsets.left - screenInsets.right ); displayWidth = Math.min( displayWidth, screenBounds.width - screenInsets.left - screenInsets.right );
} else { } else {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

View File

@@ -58,7 +58,6 @@ class FlatNativeLibrary
String classifier; String classifier;
String ext; String ext;
boolean unknownArch = false;
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) { if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) {
// Windows: requires Windows 10/11 (x86, x86_64 or aarch64) // Windows: requires Windows 10/11 (x86, x86_64 or aarch64)
@@ -91,14 +90,11 @@ class FlatNativeLibrary
classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64"; classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64";
ext = "dylib"; ext = "dylib";
} else if( SystemInfo.isLinux ) { } else if( SystemInfo.isLinux && (SystemInfo.isX86_64 || SystemInfo.isAARCH64)) {
// Linux: x86_64 or aarch64 (but also supports unknown architectures) // Linux: requires x86_64 or aarch64
classifier = SystemInfo.isAARCH64 ? "linux-arm64" classifier = SystemInfo.isAARCH64 ? "linux-arm64" : "linux-x86_64";
: (SystemInfo.isX86_64 ? "linux-x86_64"
: "linux-" + sanitize( System.getProperty( "os.arch" ) ));
ext = "so"; ext = "so";
unknownArch = !SystemInfo.isX86_64 && !SystemInfo.isAARCH64;
// Load libjawt.so (part of JRE) explicitly because it is not found // Load libjawt.so (part of JRE) explicitly because it is not found
// in all Java versions/distributions. // in all Java versions/distributions.
@@ -110,7 +106,7 @@ class FlatNativeLibrary
return; // no native library available for current OS or CPU architecture return; // no native library available for current OS or CPU architecture
// load native library // load native library
NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext, unknownArch ); NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext );
if( !nativeLibrary.isLoaded() ) if( !nativeLibrary.isLoaded() )
return; return;
@@ -132,7 +128,7 @@ class FlatNativeLibrary
FlatNativeLibrary.nativeLibrary = nativeLibrary; FlatNativeLibrary.nativeLibrary = nativeLibrary;
} }
private static NativeLibrary createNativeLibrary( String classifier, String ext, boolean unknownArch ) { private static NativeLibrary createNativeLibrary( String classifier, String ext ) {
String libraryName = "flatlaf-" + classifier; String libraryName = "flatlaf-" + classifier;
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath" // load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
@@ -143,11 +139,9 @@ class FlatNativeLibrary
if( library.isLoaded() ) if( library.isLoaded() )
return library; return library;
if( !unknownArch ) {
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName ) LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName )
+ "' not found in java.library.path '" + System.getProperty( "java.library.path" ) + "' not found in java.library.path '" + System.getProperty( "java.library.path" )
+ "'. Using extracted native library instead.", null ); + "'. Using extracted native library instead.", null );
}
} else { } else {
// try standard library naming scheme // try standard library naming scheme
// (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives') // (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives')
@@ -166,7 +160,6 @@ class FlatNativeLibrary
return new NativeLibrary( libraryFile2, true ); return new NativeLibrary( libraryFile2, true );
} }
if( !unknownArch ) {
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '"
+ libraryFile.getName() + libraryFile.getName()
+ (libraryName2 != null ? ("' or '" + libraryName2) : "") + (libraryName2 != null ? ("' or '" + libraryName2) : "")
@@ -174,7 +167,6 @@ class FlatNativeLibrary
+ "'. Using extracted native library instead.", null ); + "'. Using extracted native library instead.", null );
} }
} }
}
// load from beside the FlatLaf jar // load from beside the FlatLaf jar
// e.g. for flatlaf-3.1.jar, load flatlaf-3.1-windows-x86_64.dll (from same directory) // e.g. for flatlaf-3.1.jar, load flatlaf-3.1-windows-x86_64.dll (from same directory)
@@ -183,7 +175,7 @@ class FlatNativeLibrary
return new NativeLibrary( libraryFile, true ); return new NativeLibrary( libraryFile, true );
// load from FlatLaf jar (extract native library to temp folder) // load from FlatLaf jar (extract native library to temp folder)
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, !unknownArch ); return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
} }
/** /**
@@ -281,13 +273,6 @@ class FlatNativeLibrary
+ '-' + classifier + '.' + ext; + '-' + classifier + '.' + ext;
} }
/**
* Allow only 'a'-'z', 'A'-'Z', '0'-'9', '_' and '-' in filenames.
*/
private static String sanitize( String s ) {
return s.replaceAll( "[^a-zA-Z0-9_-]", "_" );
}
private static void loadJAWT() { private static void loadJAWT() {
try { try {
System.loadLibrary( "jawt" ); System.loadLibrary( "jawt" );

View File

@@ -49,17 +49,8 @@ class FlatNativeLinuxLibrary
} }
// direction for _NET_WM_MOVERESIZE message // direction for _NET_WM_MOVERESIZE message
// see https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html // see https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
static final int static final int MOVE = 8;
SIZE_TOPLEFT = 0,
SIZE_TOP = 1,
SIZE_TOPRIGHT = 2,
SIZE_RIGHT = 3,
SIZE_BOTTOMRIGHT = 4,
SIZE_BOTTOM = 5,
SIZE_BOTTOMLEFT = 6,
SIZE_LEFT = 7,
MOVE = 8;
private static Boolean isXWindowSystem; private static Boolean isXWindowSystem;

View File

@@ -25,6 +25,7 @@ import java.awt.Dimension;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsDevice.WindowTranslucency;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.Insets; import java.awt.Insets;
import java.awt.MouseInfo; import java.awt.MouseInfo;
@@ -32,6 +33,7 @@ import java.awt.Panel;
import java.awt.Point; import java.awt.Point;
import java.awt.PointerInfo; import java.awt.PointerInfo;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
@@ -116,8 +118,8 @@ public class FlatPopupFactory
// macOS and Linux adds drop shadow to heavy weight popups // macOS and Linux adds drop shadow to heavy weight popups
if( SystemInfo.isMacOS || SystemInfo.isLinux ) { if( SystemInfo.isMacOS || SystemInfo.isLinux ) {
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents ); NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
if( popup.popupWindow != null && isMacOSBorderSupported() ) if( popup.popupWindow != null && (isMacOSBorderSupported() || isLinuxBorderSupported( popup.popupWindow )) )
setupRoundedBorder( popup.popupWindow, owner, contents ); setupRoundedBorder( popup, popup.popupWindow, owner, contents );
return popup; return popup;
} }
@@ -127,7 +129,7 @@ public class FlatPopupFactory
{ {
NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents ); NonFlashingPopup popup = new NonFlashingPopup( getPopupForScreenOfOwner( owner, contents, x, y, true ), owner, contents );
if( popup.popupWindow != null ) if( popup.popupWindow != null )
setupRoundedBorder( popup.popupWindow, owner, contents ); setupRoundedBorder( popup, popup.popupWindow, owner, contents );
return popup; return popup;
} }
@@ -311,7 +313,7 @@ public class FlatPopupFactory
return null; return null;
Rectangle screenBounds = gc.getBounds(); Rectangle screenBounds = gc.getBounds();
Insets screenInsets = FlatUIUtils.getScreenInsets( gc ); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
int screenTop = screenBounds.y + screenInsets.top; int screenTop = screenBounds.y + screenInsets.top;
// place tooltip above mouse location if there is enough space // place tooltip above mouse location if there is enough space
@@ -369,7 +371,15 @@ public class FlatPopupFactory
FlatNativeMacLibrary.isLoaded(); FlatNativeMacLibrary.isLoaded();
} }
private static void setupRoundedBorder( Window popupWindow, Component owner, Component contents ) { private static boolean isLinuxBorderSupported( Window window ) {
return SystemInfo.isLinux &&
FlatSystemProperties.getBoolean( FlatSystemProperties.USE_ROUNDED_POPUP_BORDER, true ) &&
window.getGraphicsConfiguration().getDevice().isWindowTranslucencySupported( WindowTranslucency.PERPIXEL_TRANSPARENT );
}
private static void setupRoundedBorder( NonFlashingPopup popup,
Window popupWindow, Component owner, Component contents )
{
int borderCornerRadius = getBorderCornerRadius( owner, contents ); int borderCornerRadius = getBorderCornerRadius( owner, contents );
float borderWidth = getRoundedBorderWidth( owner, contents ); float borderWidth = getRoundedBorderWidth( owner, contents );
@@ -396,7 +406,7 @@ public class FlatPopupFactory
if( popupWindow.isDisplayable() ) { if( popupWindow.isDisplayable() ) {
// native window already created // native window already created
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor ); setupRoundedBorderImpl( popup, popupWindow, borderCornerRadius, borderWidth, borderColor );
} else { } else {
// native window not yet created --> add listener to set native border after window creation // native window not yet created --> add listener to set native border after window creation
AtomicReference<HierarchyListener> l = new AtomicReference<>(); AtomicReference<HierarchyListener> l = new AtomicReference<>();
@@ -404,7 +414,7 @@ public class FlatPopupFactory
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED && if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
(e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 ) (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 )
{ {
setupRoundedBorderImpl( popupWindow, borderCornerRadius, borderWidth, borderColor ); setupRoundedBorderImpl( popup, popupWindow, borderCornerRadius, borderWidth, borderColor );
popupWindow.removeHierarchyListener( l.get() ); popupWindow.removeHierarchyListener( l.get() );
} }
} ); } );
@@ -412,7 +422,9 @@ public class FlatPopupFactory
} }
} }
private static void setupRoundedBorderImpl( Window popupWindow, int borderCornerRadius, float borderWidth, Color borderColor ) { private static void setupRoundedBorderImpl( NonFlashingPopup popup,
Window popupWindow, int borderCornerRadius, float borderWidth, Color borderColor )
{
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
// get native window handle // get native window handle
long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow ); long hwnd = FlatNativeWindowsLibrary.getHWND( popupWindow );
@@ -432,6 +444,12 @@ public class FlatPopupFactory
// set corner radius, border width and color // set corner radius, border width and color
FlatNativeMacLibrary.setWindowRoundedBorder( popupWindow, borderCornerRadius, FlatNativeMacLibrary.setWindowRoundedBorder( popupWindow, borderCornerRadius,
borderWidth, (borderColor != null) ? borderColor.getRGB() : 0 ); borderWidth, (borderColor != null) ? borderColor.getRGB() : 0 );
} else if( SystemInfo.isLinux ) {
if( popupWindow instanceof RootPaneContainer ) {
popup.windowRoundedBorder = new FlatWindowRoundedBorder(
((RootPaneContainer)popupWindow).getRootPane(),
borderCornerRadius, borderWidth, borderColor );
}
} }
} }
@@ -464,7 +482,7 @@ public class FlatPopupFactory
"Popup.roundedBorderWidth"; "Popup.roundedBorderWidth";
Object value = getOption( owner, contents, FlatClientProperties.POPUP_ROUNDED_BORDER_WIDTH, uiKey ); Object value = getOption( owner, contents, FlatClientProperties.POPUP_ROUNDED_BORDER_WIDTH, uiKey );
return (value instanceof Number) ? ((Number)value).floatValue() : 0; return (value instanceof Number) ? ((Number)value).floatValue() : 1;
} }
//---- fixes -------------------------------------------------------------- //---- fixes --------------------------------------------------------------
@@ -577,6 +595,7 @@ public class FlatPopupFactory
// heavy weight // heavy weight
Window popupWindow; Window popupWindow;
private Color oldPopupWindowBackground; private Color oldPopupWindowBackground;
private FlatWindowRoundedBorder windowRoundedBorder;
private boolean disposed; private boolean disposed;
@@ -602,6 +621,7 @@ public class FlatPopupFactory
contents = reusePopup.contents; contents = reusePopup.contents;
popupWindow = reusePopup.popupWindow; popupWindow = reusePopup.popupWindow;
oldPopupWindowBackground = reusePopup.oldPopupWindowBackground; oldPopupWindowBackground = reusePopup.oldPopupWindowBackground;
windowRoundedBorder = reusePopup.windowRoundedBorder;
} }
NonFlashingPopup cloneForReuse() { NonFlashingPopup cloneForReuse() {
@@ -618,29 +638,6 @@ public class FlatPopupFactory
void showImpl() { void showImpl() {
if( delegate != null ) { if( delegate != null ) {
// On macOS and Linux, the empty popup window is shown in popup.show()
// (in peer.setVisible(true) invoked from Component.show()),
// but the popup content is painted later via repaint manager.
// This may cause some flicker, especially during JVM warm-up or
// when running JVM in interpreter mode (option -Xint).
// To reduce flicker, immediately paint popup content as soon as popup window becomes visible.
// This also fixes a problem with JetBrainsRuntime JVM, where sometimes the popups were empty.
if( (SystemInfo.isMacOS || SystemInfo.isLinux) && popupWindow instanceof JWindow ) {
HierarchyListener l = e -> {
if( e.getID() == HierarchyEvent.HIERARCHY_CHANGED &&
(e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0 )
{
((JWindow)popupWindow).getRootPane().paintImmediately(
0, 0, popupWindow.getWidth(), popupWindow.getHeight() );
}
};
popupWindow.addHierarchyListener( l );
try {
showPopupAndFixLocation( delegate, popupWindow );
} finally {
popupWindow.removeHierarchyListener( l );
}
} else
showPopupAndFixLocation( delegate, popupWindow ); showPopupAndFixLocation( delegate, popupWindow );
// increase tooltip size if necessary because it may be too small on HiDPI screens // increase tooltip size if necessary because it may be too small on HiDPI screens
@@ -696,25 +693,15 @@ public class FlatPopupFactory
contents = null; contents = null;
} }
if( windowRoundedBorder != null ) {
windowRoundedBorder.uninstall();
windowRoundedBorder = null;
}
if( popupWindow != null ) { if( popupWindow != null ) {
// restore background so that it can not affect other LaFs (when switching) // restore background so that it can not affect other LaFs (when switching)
// because popup windows are cached and reused // because popup windows are cached and reused
popupWindow.setBackground( oldPopupWindowBackground ); popupWindow.setBackground( oldPopupWindowBackground );
// On macOS, popupWindow.setBackground(...) invoked from constructor,
// has no affect if the popup window peer (a NSWindow) is already created,
// which is the case when reusing a cached popup window
// (see class PopupFactory.HeavyWeightPopup).
// This may result in flicker when e.g. showing a popup in a light theme,
// then switching to a dark theme and again showing a popup,
// because the underling NSWindow still has a light background,
// which may be shown shortly before the actual dark popup content is shown.
// To fix this, dispose the popup window, which disposes the NSWindow.
// The AWT popup window stays in the popup cache, but when reusing it later,
// a new peer and a new NSWindow is created and gets the correct background.
if( SystemInfo.isMacOS )
popupWindow.dispose();
popupWindow = null; popupWindow = null;
} }
} }

View File

@@ -246,7 +246,7 @@ public class FlatPopupMenuUI
// (always subtract screen insets because there is no API to detect whether // (always subtract screen insets because there is no API to detect whether
// the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar()) // the popup can overlap the taskbar; see JPopupMenu.canPopupOverlapTaskBar())
Rectangle screenBounds = gc.getBounds(); Rectangle screenBounds = gc.getBounds();
Insets screenInsets = FlatUIUtils.getScreenInsets( gc ); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc );
return FlatUIUtils.subtractInsets( screenBounds, screenInsets ); return FlatUIUtils.subtractInsets( screenBounds, screenInsets );
} }

View File

@@ -31,7 +31,6 @@ import java.awt.Window;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog; import javax.swing.JDialog;
@@ -486,12 +485,8 @@ public class FlatRootPaneUI
break; break;
case "ancestor": case "ancestor":
if( e.getNewValue() instanceof Window ) { if( e.getNewValue() instanceof Window )
if( titlePane != null && !Objects.equals( titlePane.windowStyle, FlatTitlePane.getWindowStyle( rootPane ) ) )
setTitlePane( createTitlePane() );
macClearBackgroundForTranslucentWindow( rootPane ); macClearBackgroundForTranslucentWindow( rootPane );
}
macUninstallWindowBackgroundListener( rootPane ); macUninstallWindowBackgroundListener( rootPane );
macInstallWindowBackgroundListener( rootPane ); macInstallWindowBackgroundListener( rootPane );

View File

@@ -140,6 +140,8 @@ public class FlatSpinnerUI
buttonHoverArrowColor = UIManager.getColor( "Spinner.buttonHoverArrowColor" ); buttonHoverArrowColor = UIManager.getColor( "Spinner.buttonHoverArrowColor" );
buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" ); buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" );
padding = UIManager.getInsets( "Spinner.padding" ); padding = UIManager.getInsets( "Spinner.padding" );
MigLayoutVisualPadding.install( spinner );
} }
@Override @Override
@@ -160,6 +162,8 @@ public class FlatSpinnerUI
oldStyleValues = null; oldStyleValues = null;
borderShared = null; borderShared = null;
MigLayoutVisualPadding.uninstall( spinner );
} }
@Override @Override
@@ -169,8 +173,6 @@ public class FlatSpinnerUI
addEditorFocusListener( spinner.getEditor() ); addEditorFocusListener( spinner.getEditor() );
spinner.addFocusListener( getHandler() ); spinner.addFocusListener( getHandler() );
spinner.addPropertyChangeListener( getHandler() ); spinner.addPropertyChangeListener( getHandler() );
MigLayoutVisualPadding.install( spinner );
} }
@Override @Override
@@ -182,8 +184,6 @@ public class FlatSpinnerUI
spinner.removePropertyChangeListener( getHandler() ); spinner.removePropertyChangeListener( getHandler() );
handler = null; handler = null;
MigLayoutVisualPadding.uninstall( spinner );
} }
private Handler getHandler() { private Handler getHandler() {

View File

@@ -42,6 +42,7 @@ import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
/** /**
* Support for styling components in CSS syntax. * Support for styling components in CSS syntax.
@@ -324,24 +325,22 @@ public class FlatStylingSupport
return null; return null;
Map<String, Object> oldValues = new HashMap<>(); Map<String, Object> oldValues = new HashMap<>();
outer:
for( Map.Entry<String, Object> e : style.entrySet() ) { for( Map.Entry<String, Object> e : style.entrySet() ) {
String key = e.getKey(); String key = e.getKey();
Object newValue = e.getValue(); Object newValue = e.getValue();
// handle key prefix // handle key prefix
while( key.startsWith( "[" ) ) { if( key.startsWith( "[" ) ) {
int closeIndex = key.indexOf( ']' ); if( (SystemInfo.isWindows && key.startsWith( "[win]" )) ||
if( closeIndex < 0 ) (SystemInfo.isMacOS && key.startsWith( "[mac]" )) ||
continue outer; (SystemInfo.isLinux && key.startsWith( "[linux]" )) ||
(key.startsWith( "[light]" ) && !FlatLaf.isLafDark()) ||
String prefix = key.substring( 0, closeIndex + 1 ); (key.startsWith( "[dark]" ) && FlatLaf.isLafDark()) )
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( FlatLaf.isLafDark() ); {
if( !lightOrDarkPrefix.equals( prefix ) && !FlatLaf.getUIKeyPlatformPrefixes().contains( prefix ) )
continue outer;
// prefix is known and enabled --> remove prefix // prefix is known and enabled --> remove prefix
key = key.substring( closeIndex + 1 ); key = key.substring( key.indexOf( ']' ) + 1 );
} else
continue;
} }
Object oldValue = applyProperty.apply( key, newValue ); Object oldValue = applyProperty.apply( key, newValue );

View File

@@ -39,7 +39,6 @@ import java.beans.PropertyChangeListener;
import java.util.Map; import java.util.Map;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.ActionMap; import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTable; import javax.swing.JTable;
@@ -990,14 +989,12 @@ public class FlatTableUI
FlatBooleanRenderer() { FlatBooleanRenderer() {
setHorizontalAlignment( SwingConstants.CENTER ); setHorizontalAlignment( SwingConstants.CENTER );
Icon icon = new FlatCheckBoxIcon() { setIcon( new FlatCheckBoxIcon() {
@Override @Override
protected boolean isSelected( Component c ) { protected boolean isSelected( Component c ) {
return selected; return selected;
} }
}; } );
setIcon( icon );
setDisabledIcon( icon );
} }
@Override @Override

View File

@@ -174,6 +174,8 @@ public class FlatTextFieldUI
defaultMargin = UIManager.getInsets( prefix + ".margin" ); defaultMargin = UIManager.getInsets( prefix + ".margin" );
LookAndFeel.installProperty( getComponent(), "opaque", false ); LookAndFeel.installProperty( getComponent(), "opaque", false );
MigLayoutVisualPadding.install( getComponent() );
} }
@Override @Override
@@ -191,6 +193,8 @@ public class FlatTextFieldUI
oldStyleValues = null; oldStyleValues = null;
borderShared = null; borderShared = null;
MigLayoutVisualPadding.uninstall( getComponent() );
} }
@Override @Override
@@ -200,8 +204,6 @@ public class FlatTextFieldUI
// necessary to update focus border and background // necessary to update focus border and background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null ); focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
getComponent().addFocusListener( focusListener ); getComponent().addFocusListener( focusListener );
MigLayoutVisualPadding.install( getComponent() );
} }
@Override @Override
@@ -215,8 +217,6 @@ public class FlatTextFieldUI
getComponent().getDocument().removeDocumentListener( documentListener ); getComponent().getDocument().removeDocumentListener( documentListener );
documentListener = null; documentListener = null;
} }
MigLayoutVisualPadding.uninstall( getComponent() );
} }
@Override @Override

View File

@@ -33,6 +33,7 @@ import java.awt.Image;
import java.awt.Insets; import java.awt.Insets;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter; import java.awt.event.ComponentAdapter;
@@ -89,16 +90,13 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TitlePane.iconSize Dimension * @uiDefault TitlePane.iconSize Dimension
* @uiDefault TitlePane.iconMargins Insets * @uiDefault TitlePane.iconMargins Insets
* @uiDefault TitlePane.titleMargins Insets * @uiDefault TitlePane.titleMargins Insets
* @uiDefault TitlePane.menuBarEmbedded boolean
* @uiDefault TitlePane.titleMinimumWidth int * @uiDefault TitlePane.titleMinimumWidth int
* @uiDefault TitlePane.buttonMinimumWidth int * @uiDefault TitlePane.buttonMinimumWidth int
* @uiDefault TitlePane.buttonMaximizedHeight int * @uiDefault TitlePane.buttonMaximizedHeight int
* @uiDefault TitlePane.buttonsGap int
* @uiDefault TitlePane.buttonsMargins Insets
* @uiDefault TitlePane.buttonsFillVertically boolean
* @uiDefault TitlePane.centerTitle boolean * @uiDefault TitlePane.centerTitle boolean
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean * @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
* @uiDefault TitlePane.showIconBesideTitle boolean * @uiDefault TitlePane.showIconBesideTitle boolean
* @uiDefault TitlePane.menuBarEmbedded boolean
* @uiDefault TitlePane.menuBarTitleGap int * @uiDefault TitlePane.menuBarTitleGap int
* @uiDefault TitlePane.menuBarTitleMinimumGap int * @uiDefault TitlePane.menuBarTitleMinimumGap int
* @uiDefault TitlePane.closeIcon Icon * @uiDefault TitlePane.closeIcon Icon
@@ -126,14 +124,9 @@ public class FlatTitlePane
/** @since 2.5 */ protected final boolean showIconInDialogs; /** @since 2.5 */ protected final boolean showIconInDialogs;
/** @since 2 */ protected final int noIconLeftGap; /** @since 2 */ protected final int noIconLeftGap;
protected final Dimension iconSize; protected final Dimension iconSize;
/** @since 3.6 */ protected final Insets iconMargins;
/** @since 3.6 */ protected final Insets titleMargins;
/** @since 2.4 */ protected final int titleMinimumWidth; /** @since 2.4 */ protected final int titleMinimumWidth;
/** @since 2.4 */ protected final int buttonMinimumWidth; /** @since 2.4 */ protected final int buttonMinimumWidth;
protected final int buttonMaximizedHeight; protected final int buttonMaximizedHeight;
/** @since 3.6 */ protected final int buttonsGap;
/** @since 3.6 */ protected final Insets buttonsMargins;
/** @since 3.6 */ protected final boolean buttonsFillVertically;
protected final boolean centerTitle; protected final boolean centerTitle;
protected final boolean centerTitleIfMenuBarEmbedded; protected final boolean centerTitleIfMenuBarEmbedded;
/** @since 2.4 */ protected final boolean showIconBesideTitle; /** @since 2.4 */ protected final boolean showIconBesideTitle;
@@ -153,9 +146,6 @@ public class FlatTitlePane
protected JButton restoreButton; protected JButton restoreButton;
protected JButton closeButton; protected JButton closeButton;
private JComponent iconifyMaximizeGapComp;
private JComponent maximizeCloseGapComp;
protected Window window; protected Window window;
private final Handler handler; private final Handler handler;
@@ -190,7 +180,9 @@ public class FlatTitlePane
public FlatTitlePane( JRootPane rootPane ) { public FlatTitlePane( JRootPane rootPane ) {
this.rootPane = rootPane; this.rootPane = rootPane;
windowStyle = getWindowStyle( rootPane ); Window w = SwingUtilities.getWindowAncestor( rootPane );
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
windowStyle = clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle ); titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle );
activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle ); activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle );
@@ -205,14 +197,9 @@ public class FlatTitlePane
showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true ); showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true );
noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 ); noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 );
iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle ); iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle );
iconMargins = FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle );
titleMargins = FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle );
titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 ); titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 );
buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 ); buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 );
buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 ); buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 );
buttonsGap = FlatUIUtils.getSubUIInt( "TitlePane.buttonsGap", windowStyle, 0 );
buttonsMargins = FlatUIUtils.getSubUIInsets( "TitlePane.buttonsMargins", windowStyle );
buttonsFillVertically = FlatUIUtils.getSubUIBoolean( "TitlePane.buttonsFillVertically", windowStyle, true );
centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false ); centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false );
centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true ); centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true );
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false ); showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
@@ -242,12 +229,6 @@ public class FlatTitlePane
applyComponentOrientation( rootPane.getComponentOrientation() ); applyComponentOrientation( rootPane.getComponentOrientation() );
} }
static String getWindowStyle( JRootPane rootPane ) {
Window w = SwingUtilities.getWindowAncestor( rootPane );
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
return clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
}
protected FlatTitlePaneBorder createTitlePaneBorder() { protected FlatTitlePaneBorder createTitlePaneBorder() {
return new FlatTitlePaneBorder(); return new FlatTitlePaneBorder();
} }
@@ -265,8 +246,8 @@ public class FlatTitlePane
setUI( new FlatTitleLabelUI() ); setUI( new FlatTitleLabelUI() );
} }
}; };
iconLabel.setBorder( new FlatEmptyBorder( iconMargins ) ); iconLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle ) ) );
titleLabel.setBorder( new FlatEmptyBorder( titleMargins ) ); titleLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle ) ) );
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) ); leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
leftPanel.setOpaque( false ); leftPanel.setOpaque( false );
@@ -369,15 +350,10 @@ public class FlatTitlePane
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() ); restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() ); closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
iconifyMaximizeGapComp = createButtonsGapComp();
maximizeCloseGapComp = createButtonsGapComp();
// initially hide buttons that are only supported in frames // initially hide buttons that are only supported in frames
iconifyButton.setVisible( false ); iconifyButton.setVisible( false );
maximizeButton.setVisible( false ); maximizeButton.setVisible( false );
restoreButton.setVisible( false ); restoreButton.setVisible( false );
iconifyMaximizeGapComp.setVisible( false );
maximizeCloseGapComp.setVisible( false );
buttonPanel = new JPanel() { buttonPanel = new JPanel() {
@Override @Override
@@ -389,13 +365,12 @@ public class FlatTitlePane
if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) { if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) {
// make title pane height smaller when frame is maximized // make title pane height smaller when frame is maximized
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight + buttonsMargins.top + buttonsMargins.bottom ) ) ); size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) );
} }
return size; return size;
} }
}; };
buttonPanel.setOpaque( false ); buttonPanel.setOpaque( false );
buttonPanel.setBorder( FlatUIUtils.nonUIResource( new FlatEmptyBorder( buttonsMargins ) ) );
buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) ); buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) );
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) { if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
// JRootPane.FRAME works only for frames (and not for dialogs) // JRootPane.FRAME works only for frames (and not for dialogs)
@@ -404,10 +379,8 @@ public class FlatTitlePane
// later in frameStateChanged(), which is invoked from addNotify() // later in frameStateChanged(), which is invoked from addNotify()
buttonPanel.add( iconifyButton ); buttonPanel.add( iconifyButton );
buttonPanel.add( iconifyMaximizeGapComp );
buttonPanel.add( maximizeButton ); buttonPanel.add( maximizeButton );
buttonPanel.add( restoreButton ); buttonPanel.add( restoreButton );
buttonPanel.add( maximizeCloseGapComp );
} }
buttonPanel.add( closeButton ); buttonPanel.add( closeButton );
@@ -424,17 +397,13 @@ public class FlatTitlePane
@Override @Override
public Dimension getMinimumSize() { public Dimension getMinimumSize() {
// allow the button to shrink if space is rare // allow the button to shrink if space is rare
return new Dimension( return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height );
Math.min( UIScale.scale( buttonMinimumWidth ), super.getPreferredSize().width ),
super.getMinimumSize().height );
} }
@Override @Override
public Dimension getMaximumSize() { public Dimension getMaximumSize() {
// allow the button to fill whole button area height // allow the button to fill whole button area height
// see also BasicMenuUI.getMaximumSize() // see also BasicMenuUI.getMaximumSize()
return buttonsFillVertically return new Dimension( super.getMaximumSize().width, Short.MAX_VALUE );
? new Dimension( super.getMaximumSize().width, Short.MAX_VALUE )
: super.getMaximumSize();
} }
}; };
button.setFocusable( false ); button.setFocusable( false );
@@ -445,14 +414,6 @@ public class FlatTitlePane
return button; return button;
} }
private JComponent createButtonsGapComp() {
JComponent gapComp = new JPanel();
gapComp.setOpaque( false );
gapComp.setMinimumSize( new Dimension( 0, 0 ) );
gapComp.setPreferredSize( new Dimension( UIScale.scale( buttonsGap ), 0 ) );
return gapComp;
}
protected void activeChanged( boolean active ) { protected void activeChanged( boolean active ) {
Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ); Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null );
Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null ); Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null );
@@ -474,9 +435,6 @@ public class FlatTitlePane
closeButton.setForeground( foreground ); closeButton.setForeground( foreground );
// this is necessary because hover/pressed colors are derived from background color // this is necessary because hover/pressed colors are derived from background color
// (since FlatWindowAbstractIcon now invokes FlatTitlePane.getBackground()
// to get base color, this is no longer necessary, but keep it for compatibility;
// e.g. for custom window icons)
iconifyButton.setBackground( background ); iconifyButton.setBackground( background );
maximizeButton.setBackground( background ); maximizeButton.setBackground( background );
restoreButton.setBackground( background ); restoreButton.setBackground( background );
@@ -536,13 +494,6 @@ public class FlatTitlePane
maximizeButton.setVisible( false ); maximizeButton.setVisible( false );
restoreButton.setVisible( false ); restoreButton.setVisible( false );
} }
boolean iconifyVisible = iconifyButton.isVisible();
boolean maximizeVisible = maximizeButton.isVisible();
boolean restoreVisible = restoreButton.isVisible();
boolean closeVisible = closeButton.isVisible();
iconifyMaximizeGapComp.setVisible( iconifyVisible && (maximizeVisible || restoreVisible || closeVisible) );
maximizeCloseGapComp.setVisible( closeVisible && (maximizeVisible || restoreVisible) );
} }
protected void updateIcon() { protected void updateIcon() {
@@ -796,17 +747,12 @@ public class FlatTitlePane
if( isFullWindowContent() ) if( isFullWindowContent() )
return; return;
g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
}
@Override
public Color getBackground() {
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime // not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
return (UIManager.getBoolean( "TitlePane.unifiedBackground" ) && g.setColor( (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null) clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
? FlatUIUtils.getParentBackground( this ) ? FlatUIUtils.getParentBackground( this )
: super.getBackground(); : getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
} }
/** /**
@@ -914,7 +860,7 @@ public class FlatTitlePane
// screen insets are in physical size, except for Java 15+ // screen insets are in physical size, except for Java 15+
// (see https://bugs.openjdk.java.net/browse/JDK-8243925) // (see https://bugs.openjdk.java.net/browse/JDK-8243925)
// and except for Java 8 on secondary screens where primary screen is scaled // and except for Java 8 on secondary screens where primary screen is scaled
Insets screenInsets = FlatUIUtils.getScreenInsets( gc ); Insets screenInsets = window.getToolkit().getScreenInsets( gc );
// maximized bounds are required in physical size, except for Java 15+ // maximized bounds are required in physical size, except for Java 15+
// (see https://bugs.openjdk.java.net/browse/JDK-8231564 and // (see https://bugs.openjdk.java.net/browse/JDK-8231564 and
@@ -1148,7 +1094,6 @@ public class FlatTitlePane
if( !c.isDisplayable() || !c.isVisible() || !contains( c, x, y ) || c == mouseLayer ) if( !c.isDisplayable() || !c.isVisible() || !contains( c, x, y ) || c == mouseLayer )
return true; // continue checking with next component return true; // continue checking with next component
// check enabled component that has mouse listeners
if( c.isEnabled() && if( c.isEnabled() &&
(c.getMouseListeners().length > 0 || (c.getMouseListeners().length > 0 ||
c.getMouseMotionListeners().length > 0) ) c.getMouseMotionListeners().length > 0) )
@@ -1472,9 +1417,22 @@ debug*/
private Point dragOffset; private Point dragOffset;
private boolean linuxNativeMove; private boolean linuxNativeMove;
private long lastSingleClickWhen;
@Override @Override
public void mouseClicked( MouseEvent e ) { public void mouseClicked( MouseEvent e ) {
// on Linux, when using native library, the mouse clicked event
// is usually not sent and maximize/restore is done in mouse pressed event
// this check is here for the case that a mouse clicked event comes through for some reason
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
// see comment in mousePressed()
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
lastSingleClickWhen = 0;
maximizeOrRestore();
}
return;
}
if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) { if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) {
if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) { if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) {
// double-click on icon closes window // double-click on icon closes window
@@ -1505,6 +1463,42 @@ debug*/
dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window ); dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window );
linuxNativeMove = false; linuxNativeMove = false;
// on Linux, move or maximize/restore window
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
// The fired Java mouse events, when doing a double-click and the first click
// sends a _NET_WM_MOVERESIZE message, are different for various Linux distributions:
// CentOS 7 (GNOME 3.28.2, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
// Ubuntu 20.04 (GNOME 3.36.1, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
// Ubuntu 22.04 (GNOME 42.2, Wayland): PRESSED(clickCount=1) RELEASED(clickCount=1) CLICKED(clickCount=1)
// Kubuntu 22.04 (KDE 5.24.4, X11): PRESSED(clickCount=1) PRESSED(clickCount=1) RELEASED(clickCount=1)
// double-click is not always recognized in Java when using _NET_WM_MOVERESIZE message
int clickCount = e.getClickCount();
if( clickCount == 1 && lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() )
clickCount = 2;
switch( clickCount ) {
case 1:
// move window via _NET_WM_MOVERESIZE message
e.consume();
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
lastSingleClickWhen = e.getWhen();
break;
case 2:
// maximize/restore on double-click
// also done here because no mouse clicked event is sent when using _NET_WM_MOVERESIZE message
lastSingleClickWhen = 0;
maximizeOrRestore();
break;
}
}
}
private int getMultiClickInterval() {
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "awt.multiClickInterval" );
return (value instanceof Integer) ? (Integer) value : 500;
} }
@Override public void mouseReleased( MouseEvent e ) {} @Override public void mouseReleased( MouseEvent e ) {}
@@ -1527,13 +1521,6 @@ debug*/
if( hasNativeCustomDecoration() ) if( hasNativeCustomDecoration() )
return; // do nothing if having native window border return; // do nothing if having native window border
// on Linux, move window using window manager
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
if( linuxNativeMove )
return;
}
// restore window if it is maximized // restore window if it is maximized
if( window instanceof Frame ) { if( window instanceof Frame ) {
Frame frame = (Frame) window; Frame frame = (Frame) window;

View File

@@ -26,7 +26,6 @@ import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets; import java.awt.Insets;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.Paint; import java.awt.Paint;
@@ -35,7 +34,6 @@ import java.awt.RenderingHints;
import java.awt.Shape; import java.awt.Shape;
import java.awt.Stroke; import java.awt.Stroke;
import java.awt.SystemColor; import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
@@ -413,18 +411,8 @@ public class FlatUIUtils
GraphicsConfiguration gc = c.getGraphicsConfiguration(); GraphicsConfiguration gc = c.getGraphicsConfiguration();
GraphicsDevice gd = (gc != null) ? gc.getDevice() : null; GraphicsDevice gd = (gc != null) ? gc.getDevice() : null;
Window fullScreenWindow = (gd != null) ? gd.getFullScreenWindow() : null; Window fullScreenWindow = (gd != null) ? gd.getFullScreenWindow() : null;
return (fullScreenWindow != null && fullScreenWindow == SwingUtilities.windowForComponent( c )); return (fullScreenWindow != null &&
} (fullScreenWindow == c || fullScreenWindow == SwingUtilities.windowForComponent( c )));
/** @since 3.6.1 */
public static Insets getScreenInsets( GraphicsConfiguration gc ) {
// on Linux, getScreenInsets() may report wrong values in multi-screen setups
// see https://github.com/apache/netbeans/issues/8532#issuecomment-2909687016
if( SystemInfo.isLinux &&
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length > 1 )
return new Insets( 0, 0, 0, 0 );
return Toolkit.getDefaultToolkit().getScreenInsets( gc );
} }
public static Boolean isRoundRect( Component c ) { public static Boolean isRoundRect( Component c ) {

View File

@@ -188,7 +188,7 @@ public abstract class FlatWindowResizer
protected abstract Dimension getWindowMinimumSize(); protected abstract Dimension getWindowMinimumSize();
protected abstract Dimension getWindowMaximumSize(); protected abstract Dimension getWindowMaximumSize();
protected void beginResizing( int resizeDir, MouseEvent e ) {} protected void beginResizing( int resizeDir ) {}
protected void endResizing() {} protected void endResizing() {}
//---- interface PropertyChangeListener ---- //---- interface PropertyChangeListener ----
@@ -331,7 +331,7 @@ public abstract class FlatWindowResizer
protected Rectangle getParentBounds() { protected Rectangle getParentBounds() {
GraphicsConfiguration gc = window.getGraphicsConfiguration(); GraphicsConfiguration gc = window.getGraphicsConfiguration();
Rectangle bounds = gc.getBounds(); Rectangle bounds = gc.getBounds();
Insets insets = FlatUIUtils.getScreenInsets( gc ); Insets insets = window.getToolkit().getScreenInsets( gc );
return new Rectangle( bounds.x + insets.left, bounds.y + insets.top, return new Rectangle( bounds.x + insets.left, bounds.y + insets.top,
bounds.width - insets.left - insets.right, bounds.width - insets.left - insets.right,
bounds.height - insets.top - insets.bottom ); bounds.height - insets.top - insets.bottom );
@@ -370,25 +370,7 @@ public abstract class FlatWindowResizer
} }
@Override @Override
protected void beginResizing( int resizeDir, MouseEvent e ) { protected void beginResizing( int resizeDir ) {
// on Linux, resize window using window manager
if( SystemInfo.isLinux && window != null && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
int direction = -1;
switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOP; break;
case S_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOM; break;
case W_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_LEFT; break;
case E_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_RIGHT; break;
case NW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPLEFT; break;
case NE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPRIGHT; break;
case SW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMLEFT; break;
case SE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMRIGHT; break;
}
if( direction >= 0 && FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, direction ) )
return;
}
centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() ); centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() );
centerComp.setCursor( getPredefinedCursor( resizeDir ) ); centerComp.setCursor( getPredefinedCursor( resizeDir ) );
centerComp.setVisible( true ); centerComp.setVisible( true );
@@ -480,7 +462,7 @@ public abstract class FlatWindowResizer
} }
@Override @Override
protected void beginResizing( int resizeDir, MouseEvent e ) { protected void beginResizing( int resizeDir ) {
int direction = 0; int direction = 0;
switch( resizeDir ) { switch( resizeDir ) {
case N_RESIZE_CURSOR: direction = NORTH; break; case N_RESIZE_CURSOR: direction = NORTH; break;
@@ -599,7 +581,7 @@ debug*/
dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen; dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen;
dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen; dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen;
beginResizing( resizeDir, e ); beginResizing( resizeDir );
} }
@Override @Override

View File

@@ -0,0 +1,361 @@
/*
* Copyright 2025 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.ui;
import static javax.swing.SwingConstants.*;
import java.awt.Color;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.IllegalComponentStateException;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import com.formdev.flatlaf.util.UIScale;
/**
* Rounded border for {@link Window}.
* Used for popups and for FlatLaf window decorations.
* <p>
* Border is painted only if window is not maximized (in both directions) and
* not in full screen mode. If maximized in one direction (vertically or horizontally),
* then a square border is painted.
* <p>
* Note: The rootpane of the window should have a {@link FlatEmptyBorder} with
* same insets as border width used in this class.
*
* @author Karl Tauber
* @since 3.6
*/
public class FlatWindowRoundedBorder
implements PropertyChangeListener, ComponentListener
{
protected final JRootPane rootPane;
protected final int borderCornerRadius;
protected final float borderWidth;
protected final Color borderColor;
protected final Shape cornerShape;
// edges
protected final RoundedBorderComponent northComp;
protected final RoundedBorderComponent southComp;
protected final RoundedBorderComponent westComp;
protected final RoundedBorderComponent eastComp;
// corners
protected final RoundedBorderComponent northWestComp;
protected final RoundedBorderComponent northEastComp;
protected final RoundedBorderComponent southWestComp;
protected final RoundedBorderComponent southEastComp;
protected Window window;
protected boolean windowIsRounded;
public FlatWindowRoundedBorder( JRootPane rootPane, int borderCornerRadius,
float borderWidth, Color borderColor )
{
this.rootPane = rootPane;
this.borderCornerRadius = borderCornerRadius;
this.borderWidth = borderWidth;
this.borderColor = borderColor;
// create shape used to paint rounded corners
cornerShape = createCornerShape();
// create edges
northComp = new RoundedBorderComponent( NORTH );
southComp = new RoundedBorderComponent( SOUTH );
westComp = new RoundedBorderComponent( WEST );
eastComp = new RoundedBorderComponent( EAST );
// create corners
northWestComp = new RoundedBorderComponent( NORTH_WEST );
northEastComp = new RoundedBorderComponent( NORTH_EAST );
southWestComp = new RoundedBorderComponent( SOUTH_WEST );
southEastComp = new RoundedBorderComponent( SOUTH_EAST );
// insert before layered pane
int insertIndex = rootPane.getComponentCount() - 1;
JLayeredPane layeredPane = rootPane.getLayeredPane();
for( int i = insertIndex; i >= 0; i-- ) {
if( rootPane.getComponent( insertIndex ) == layeredPane )
break;
}
// add edges
rootPane.add( northComp, insertIndex++ );
rootPane.add( southComp, insertIndex++ );
rootPane.add( westComp, insertIndex++ );
rootPane.add( eastComp, insertIndex++ );
// add corners
rootPane.add( northWestComp, insertIndex++ );
rootPane.add( northEastComp, insertIndex++ );
rootPane.add( southWestComp, insertIndex++ );
rootPane.add( southEastComp, insertIndex++ );
// add listeners
rootPane.addComponentListener( this );
rootPane.addPropertyChangeListener( "ancestor", this );
if( rootPane.isDisplayable() )
addNotify();
else
updateVisibility();
}
public void uninstall() {
removeNotify();
// remove listeners
rootPane.removeComponentListener( this );
rootPane.removePropertyChangeListener( "ancestor", this );
// remove edges
rootPane.remove( northComp );
rootPane.remove( southComp );
rootPane.remove( westComp );
rootPane.remove( eastComp );
// remove corners
rootPane.remove( northWestComp );
rootPane.remove( northEastComp );
rootPane.remove( southWestComp );
rootPane.remove( southEastComp );
}
public void doLayout() {
if( !northComp.isVisible() )
return;
int x = 0;
int y = 0;
int width = rootPane.getWidth();
int height = rootPane.getHeight();
if( width <= 0 || height <= 0 )
return;
// for layout, round-up scaled border width and radius to ensure that components are large enough
int lineWidth = (int) Math.ceil( UIScale.scale( borderWidth ) );
int cornerSize = (windowIsRounded && lineWidth > 0)
? (int) Math.ceil( UIScale.scale( (float) borderCornerRadius ) )
: 0;
int cornerSize2x = cornerSize * 2;
// edges
northComp.setBounds( x + cornerSize, y, width - cornerSize2x, lineWidth );
southComp.setBounds( x + cornerSize, y + height - lineWidth, width - cornerSize2x, lineWidth );
westComp.setBounds( x, y + cornerSize, lineWidth, height - cornerSize2x );
eastComp.setBounds( x + width - lineWidth, y + cornerSize, lineWidth, height - cornerSize2x );
// corners
northWestComp.setBounds( x, y, cornerSize, cornerSize );
northEastComp.setBounds( x + width - cornerSize, y, cornerSize, cornerSize );
southWestComp.setBounds( x, y + height - cornerSize, cornerSize, cornerSize );
southEastComp.setBounds( x + width - cornerSize, y + height - cornerSize, cornerSize, cornerSize );
}
protected void addNotify() {
Container parent = rootPane.getParent();
window = (parent instanceof Window) ? (Window) parent : null;
updateVisibility();
updateWindowShape();
doLayout();
}
protected void removeNotify() {
if( window != null ) {
window.setShape( null );
window = null;
}
updateVisibility();
}
protected void updateVisibility() {
boolean visible = needsBorder();
if( visible == northComp.isVisible() )
return;
// edges
northComp.setVisible( visible );
southComp.setVisible( visible );
westComp.setVisible( visible );
eastComp.setVisible( visible );
// corners
northWestComp.setVisible( visible );
northEastComp.setVisible( visible );
southWestComp.setVisible( visible );
southEastComp.setVisible( visible );
}
protected boolean needsBorder() {
if( window == null || FlatUIUtils.isFullScreen( window ) )
return false;
if( window instanceof Frame )
return (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != Frame.MAXIMIZED_BOTH;
return true;
}
protected void updateWindowShape() {
windowIsRounded = false;
if( window == null )
return;
if( !northComp.isVisible() ||
(window instanceof Frame && (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0) )
{
window.setShape( null );
return;
}
int arc = UIScale.scale( borderCornerRadius * 2 );
// use a slightly smaller arc for the shape so that at least parts of
// the antialiased arc outside are shown
arc -= 2;
if( arc > 0 ) {
try {
window.setShape( new RoundRectangle2D.Float( 0, 0,
rootPane.getWidth(), rootPane.getHeight(), arc, arc ) );
windowIsRounded = true;
} catch( IllegalComponentStateException | UnsupportedOperationException ex ) {
window.setShape( null );
}
} else
window.setShape( null );
}
protected Shape createCornerShape() {
float lineWidth = UIScale.scale( borderWidth );
int arc = UIScale.scale( borderCornerRadius * 2 );
int wh = arc * 3;
float innerArc = arc - (lineWidth * 2);
float innerWH = wh - (lineWidth * 2);
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new RoundRectangle2D.Float( 0, 0, wh, wh, arc, arc ), false );
path.append( new RoundRectangle2D.Float( lineWidth, lineWidth, innerWH, innerWH, innerArc, innerArc ), false );
Area area = new Area( path );
int cornerSize = (int) Math.ceil( UIScale.scale( (float) borderCornerRadius ) );
area.intersect( new Area( new Rectangle2D.Float( 0, 0, cornerSize, cornerSize ) ) );
return area;
}
//---- interface PropertyChangeListener ----
@Override
public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case "ancestor":
if( e.getNewValue() != null )
addNotify();
else
removeNotify();
break;
}
}
//---- interface ComponentListener ----
@Override
public void componentResized( ComponentEvent e ) {
updateVisibility();
updateWindowShape();
doLayout();
}
@Override public void componentMoved( ComponentEvent e ) {}
@Override public void componentShown( ComponentEvent e ) {}
@Override public void componentHidden( ComponentEvent e ) {}
//---- class RoundedBorderComponent ---------------------------------------
protected class RoundedBorderComponent
extends JComponent
{
private final int position;
protected RoundedBorderComponent( int position ) {
this.position = position;
}
@Override
public void paint( Graphics g ) {
Graphics2D g2 = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
float lineWidth = UIScale.scale( borderWidth );
/*debug
g.setColor( java.awt.Color.green );
g.drawRect( 0, 0, width - 1, height - 1 );
debug*/
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
g.setColor( borderColor );
switch( position ) {
case NORTH: g2.fill( new Rectangle2D.Float( 0, 0, width, lineWidth ) ); break;
case SOUTH: g2.fill( new Rectangle2D.Float( 0, height - lineWidth, width, lineWidth ) ); break;
case WEST: g2.fill( new Rectangle2D.Float( 0, 0, lineWidth, height ) ); break;
case EAST: g2.fill( new Rectangle2D.Float( width - lineWidth, 0, lineWidth, height ) ); break;
case NORTH_WEST:
g2.fill( cornerShape );
break;
case NORTH_EAST:
g2.translate( width, 0 );
g2.rotate( Math.toRadians( 90 ) );
g2.fill( cornerShape );
break;
case SOUTH_WEST:
g2.translate( 0, height );
g2.rotate( Math.toRadians( -90 ) );
g2.fill( cornerShape );
break;
case SOUTH_EAST:
g2.translate( width, height );
g2.rotate( Math.toRadians( 180 ) );
g2.fill( cornerShape );
break;
}
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
}
}
}

View File

@@ -21,7 +21,6 @@ import java.awt.Dialog;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Frame; import java.awt.Frame;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Window; import java.awt.Window;
@@ -40,7 +39,6 @@ import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList; import javax.swing.event.EventListenerList;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
// //
// Interesting resources: // Interesting resources:
@@ -284,8 +282,6 @@ class FlatWindowsNativeWindowBorder
HTMINBUTTON = 8, HTMINBUTTON = 8,
HTMAXBUTTON = 9, HTMAXBUTTON = 9,
HTTOP = 12, HTTOP = 12,
HTTOPLEFT = 13,
HTTOPRIGHT = 14,
HTCLOSE = 20; HTCLOSE = 20;
private Window window; private Window window;
@@ -345,31 +341,6 @@ class FlatWindowsNativeWindowBorder
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen // scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
Point pt = scaleDown( x, y ); Point pt = scaleDown( x, y );
// limit top resize border to 4px, which seems to be standard for modern WinUI apps
if( isOnResizeBorder && pt.y > UIScale.scale( 4 ) )
isOnResizeBorder = false;
if( isOnResizeBorder ) {
Insets insets = window.getInsets();
// return HTTOPLEFT if mouse is over top resize border on left side
// - hovering mouse shows top-left resize cursor
// - left-click-and-drag resizes window
if( pt.x <= insets.left + UIScale.scale( 12 ) )
return HTTOPLEFT;
// return HTTOPRIGHT if mouse is over top resize border on right side
// - hovering mouse shows top-right resize cursor
// - left-click-and-drag resizes window
if( pt.x >= window.getWidth() - insets.right - UIScale.scale( 12 ) )
return HTTOPRIGHT;
// return HTTOP if mouse is over top resize border
// - hovering mouse shows vertical resize cursor
// - left-click-and-drag vertically resizes window
return HTTOP;
}
// return HTSYSMENU if mouse is over application icon // return HTSYSMENU if mouse is over application icon
// - left-click on HTSYSMENU area shows system menu // - left-click on HTSYSMENU area shows system menu
// - double-left-click sends WM_CLOSE // - double-left-click sends WM_CLOSE
@@ -393,6 +364,12 @@ class FlatWindowsNativeWindowBorder
if( contains( closeButtonBounds, pt ) ) if( contains( closeButtonBounds, pt ) )
return HTCLOSE; return HTCLOSE;
// return HTTOP if mouse is over top resize border
// - hovering mouse shows vertical resize cursor
// - left-click and drag vertically resizes window
if( isOnResizeBorder )
return HTTOP;
boolean isOnTitleBar = (pt.y < titleBarHeight); boolean isOnTitleBar = (pt.y < titleBarHeight);
if( isOnTitleBar ) { if( isOnTitleBar ) {
// return HTCLIENT if mouse is over any Swing component in title bar // return HTCLIENT if mouse is over any Swing component in title bar

View File

@@ -21,7 +21,7 @@ import java.util.function.BiPredicate;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class StackUtils class StackUtils
{ {
private static final StackUtils INSTANCE = new StackUtilsImpl(); private static final StackUtils INSTANCE = new StackUtilsImpl();

View File

@@ -224,9 +224,6 @@ public class ColorFunctions
if( functions.length == 1 && functions[0] instanceof Mix ) { if( functions.length == 1 && functions[0] instanceof Mix ) {
Mix mixFunction = (Mix) functions[0]; Mix mixFunction = (Mix) functions[0];
return mix( color, mixFunction.color2, mixFunction.weight / 100 ); return mix( color, mixFunction.color2, mixFunction.weight / 100 );
} else if( functions.length == 1 && functions[0] instanceof Mix2 ) {
Mix2 mixFunction = (Mix2) functions[0];
return mix( mixFunction.color1, color, mixFunction.weight / 100 );
} }
// convert RGB to HSL // convert RGB to HSL
@@ -389,11 +386,7 @@ public class ColorFunctions
//---- class Mix ---------------------------------------------------------- //---- class Mix ----------------------------------------------------------
/** /**
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}. * Mix two colors.
* First color is passed to {@link #apply(float[])}.
* Second color is {@link #color2}.
* <p>
* Use {@link Mix2} to tint or shade color.
* *
* @since 1.6 * @since 1.6
*/ */
@@ -427,44 +420,4 @@ public class ColorFunctions
return String.format( "mix(#%08x,%.0f%%)", color2.getRGB(), weight ); return String.format( "mix(#%08x,%.0f%%)", color2.getRGB(), weight );
} }
} }
//---- class Mix2 ---------------------------------------------------------
/**
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}.
* First color is {@link #color1}.
* Second color is passed to {@link #apply(float[])}.
*
* @since 3.6
*/
public static class Mix2
implements ColorFunction
{
public final Color color1;
public final float weight;
public Mix2( Color color1, float weight ) {
this.color1 = color1;
this.weight = weight;
}
@Override
public void apply( float[] hsla ) {
// convert from HSL to RGB because color mixing is done on RGB values
Color color2 = HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
// mix
Color color = mix( color1, color2, weight / 100 );
// convert RGB to HSL
float[] hsl = HSLColor.fromRGB( color );
System.arraycopy( hsl, 0, hsla, 0, hsl.length );
hsla[3] = (color.getAlpha() / 255f) * 100;
}
@Override
public String toString() {
return String.format( "mix2(#%08x,%.0f%%)", color1.getRGB(), weight );
}
}
} }

View File

@@ -16,7 +16,6 @@
package com.formdev.flatlaf.util; package com.formdev.flatlaf.util;
import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
@@ -28,9 +27,7 @@ import java.awt.geom.Rectangle2D;
import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.RepaintManager; import javax.swing.RepaintManager;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.ui.StackUtils;
/** /**
* @author Karl Tauber * @author Karl Tauber
@@ -326,19 +323,6 @@ public class HiDPIUtils
public void drawGlyphVector( GlyphVector g, float x, float y ) { public void drawGlyphVector( GlyphVector g, float x, float y ) {
super.drawGlyphVector( g, x, y + yCorrection ); super.drawGlyphVector( g, x, y + yCorrection );
} }
@Override
public void fillRect( int x, int y, int width, int height ) {
// fix hard coded black color in HRuleView.paint() of '<hr noshade>'
if( super.getColor() == Color.black &&
StackUtils.wasInvokedFrom( "javax.swing.text.html.HRuleView", "paint", 4 ) )
{
super.setColor( FlatLaf.isLafDark() ? Color.lightGray : Color.darkGray );
super.fillRect( x, y, width, height );
super.setColor( Color.black );
} else
super.fillRect( x, y, width, height );
}
}; };
} }

View File

@@ -31,7 +31,6 @@ public class SystemInfo
public static final boolean isWindows; public static final boolean isWindows;
public static final boolean isMacOS; public static final boolean isMacOS;
public static final boolean isLinux; public static final boolean isLinux;
/** @since 3.6 */ public static final boolean isUnknownOS;
// OS versions // OS versions
public static final long osVersion; public static final long osVersion;
@@ -60,7 +59,6 @@ public class SystemInfo
public static final boolean isJetBrainsJVM_11_orLater; public static final boolean isJetBrainsJVM_11_orLater;
// UI toolkits // UI toolkits
/** @since 3.6 */ public static final boolean isGNOME;
public static final boolean isKDE; public static final boolean isKDE;
// other // other
@@ -77,7 +75,6 @@ public class SystemInfo
isWindows = osName.startsWith( "windows" ); isWindows = osName.startsWith( "windows" );
isMacOS = osName.startsWith( "mac" ); isMacOS = osName.startsWith( "mac" );
isLinux = osName.startsWith( "linux" ); isLinux = osName.startsWith( "linux" );
isUnknownOS = !isWindows && !isMacOS && !isLinux;
// OS versions // OS versions
osVersion = scanVersion( System.getProperty( "os.version" ) ); osVersion = scanVersion( System.getProperty( "os.version" ) );
@@ -107,13 +104,7 @@ public class SystemInfo
isJetBrainsJVM_11_orLater = isJetBrainsJVM && isJava_11_orLater; isJetBrainsJVM_11_orLater = isJetBrainsJVM && isJava_11_orLater;
// UI toolkits // UI toolkits
String desktop = isLinux ? System.getenv( "XDG_CURRENT_DESKTOP" ) : null; isKDE = (isLinux && System.getenv( "KDE_FULL_SESSION" ) != null);
isGNOME = (isLinux &&
(System.getenv( "GNOME_DESKTOP_SESSION_ID" ) != null ||
(desktop != null && desktop.contains( "GNOME" ))));
isKDE = (isLinux &&
(System.getenv( "KDE_FULL_SESSION" ) != null ||
(desktop != null && desktop.contains( "KDE" ))));
// other // other
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" ); isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );

View File

@@ -61,6 +61,7 @@ Component.arrowType = triangle
#---- ProgressBar ---- #---- ProgressBar ----
ProgressBar.foreground = darken(@foreground,10%) ProgressBar.foreground = darken(@foreground,10%)
ProgressBar.selectionForeground = @background
#---- RadioButton ---- #---- RadioButton ----

View File

@@ -34,7 +34,7 @@
# general background and foreground (text color) # general background and foreground (text color)
@background = #3c3f41 @background = #3c3f41
@foreground = #ddd @foreground = #bbb
@disabledBackground = @background @disabledBackground = @background
@disabledForeground = shade(@foreground,25%) @disabledForeground = shade(@foreground,25%)
@@ -45,7 +45,7 @@
# selection # selection
@selectionBackground = @accentSelectionBackground @selectionBackground = @accentSelectionBackground
@selectionForeground = contrast(@selectionBackground, shade(@background), tint(@foreground), 25%) @selectionForeground = contrast(@selectionBackground, @background, @foreground, 25%)
@selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15) @selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15)
@selectionInactiveForeground = @foreground @selectionInactiveForeground = @foreground
@@ -187,8 +187,6 @@ Component.error.borderColor = desaturate($Component.error.focusedBorderColor,25%
Component.error.focusedBorderColor = #8b3c3c Component.error.focusedBorderColor = #8b3c3c
Component.warning.borderColor = darken(desaturate($Component.warning.focusedBorderColor,20%),10%) Component.warning.borderColor = darken(desaturate($Component.warning.focusedBorderColor,20%),10%)
Component.warning.focusedBorderColor = #ac7920 Component.warning.focusedBorderColor = #ac7920
Component.success.borderColor = desaturate($Component.success.focusedBorderColor,25%)
Component.success.focusedBorderColor = #648b3c
Component.custom.borderColor = desaturate(#f00,50%,relative derived noAutoInverse) Component.custom.borderColor = desaturate(#f00,50%,relative derived noAutoInverse)
@@ -248,7 +246,6 @@ PasswordField.revealIconColor = @foreground
#---- Popup ---- #---- Popup ----
[mac]Popup.roundedBorderWidth = 1
Popup.dropShadowColor = #000 Popup.dropShadowColor = #000
Popup.dropShadowOpacity = 0.25 Popup.dropShadowOpacity = 0.25
@@ -264,7 +261,7 @@ PopupMenu.hoverScrollArrowBackground = lighten(@background,5%)
ProgressBar.background = lighten(@background,8%) ProgressBar.background = lighten(@background,8%)
ProgressBar.foreground = @accentSliderColor ProgressBar.foreground = @accentSliderColor
ProgressBar.selectionBackground = @foreground ProgressBar.selectionBackground = @foreground
ProgressBar.selectionForeground = contrast($ProgressBar.foreground, shade(@background), tint(@foreground), 25%) ProgressBar.selectionForeground = contrast($ProgressBar.foreground, @background, @foreground, 25%)
#---- RootPane ---- #---- RootPane ----
@@ -276,7 +273,7 @@ RootPane.inactiveBorderColor = lighten(@background,5%,derived)
#---- ScrollBar ---- #---- ScrollBar ----
ScrollBar.track = lighten(@background,1%,derived noAutoInverse) ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
ScrollBar.thumb = lighten($ScrollBar.track,15%,derived noAutoInverse) ScrollBar.thumb = lighten($ScrollBar.track,10%,derived noAutoInverse)
ScrollBar.hoverTrackColor = lighten($ScrollBar.track,4%,derived noAutoInverse) ScrollBar.hoverTrackColor = lighten($ScrollBar.track,4%,derived noAutoInverse)
ScrollBar.hoverThumbColor = lighten($ScrollBar.thumb,10%,derived noAutoInverse) ScrollBar.hoverThumbColor = lighten($ScrollBar.thumb,10%,derived noAutoInverse)
ScrollBar.pressedThumbColor = lighten($ScrollBar.thumb,15%,derived noAutoInverse) ScrollBar.pressedThumbColor = lighten($ScrollBar.thumb,15%,derived noAutoInverse)
@@ -286,7 +283,7 @@ ScrollBar.pressedButtonBackground = lighten(@background,10%,derived noAutoInvers
#---- Separator ---- #---- Separator ----
Separator.foreground = tint(@background,15%) Separator.foreground = tint(@background,10%)
#---- Slider ---- #---- Slider ----
@@ -343,13 +340,8 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
#---- TitlePane ---- #---- TitlePane ----
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%) TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived) TitlePane.buttonHoverBackground = lighten($TitlePane.background,15%,derived)
TitlePane.buttonPressedBackground = lighten($TitlePane.background,6%,derived) TitlePane.buttonPressedBackground = lighten($TitlePane.background,10%,derived)
# Linux
[linux]TitlePane.buttonBackground = lighten($TitlePane.background,5%,derived)
[linux]TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
[linux]TitlePane.buttonPressedBackground = lighten($TitlePane.background,15%,derived)
#---- ToggleButton ---- #---- ToggleButton ----

View File

@@ -50,9 +50,6 @@ mini.font = -3
#defaultFont = ... #defaultFont = ...
# font weights # font weights
# fallback for unknown platform
light.font = +0
semibold.font = +0
# Windows # Windows
[win]light.font = "Segoe UI Light" [win]light.font = "Segoe UI Light"
[win]semibold.font = "Segoe UI Semibold" [win]semibold.font = "Segoe UI Semibold"
@@ -62,12 +59,15 @@ semibold.font = +0
# Linux # Linux
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light" [linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold" [linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold"
# fallback for unknown platform
light.font = +0
semibold.font = +0
# monospaced # monospaced
monospaced.font = Monospaced
[win]monospaced.font = Monospaced [win]monospaced.font = Monospaced
[mac]monospaced.font = Menlo, Monospaced [mac]monospaced.font = Menlo, Monospaced
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced [linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
monospaced.font = Monospaced
# styles # styles
[style].h00 = font: $h00.font [style].h00 = font: $h00.font
@@ -289,7 +289,7 @@ ComboBox.popupInsets = 0,0,0,0
ComboBox.selectionInsets = 0,0,0,0 ComboBox.selectionInsets = 0,0,0,0
ComboBox.selectionArc = 0 ComboBox.selectionArc = 0
ComboBox.borderCornerRadius = $Popup.borderCornerRadius ComboBox.borderCornerRadius = $Popup.borderCornerRadius
[mac]ComboBox.roundedBorderWidth = $Popup.roundedBorderWidth ComboBox.roundedBorderWidth = $Popup.roundedBorderWidth
#---- Component ---- #---- Component ----
@@ -506,7 +506,7 @@ PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
#---- Popup ---- #---- Popup ----
Popup.borderCornerRadius = 4 Popup.borderCornerRadius = 4
[mac]Popup.roundedBorderWidth = 0 Popup.roundedBorderWidth = 1
Popup.dropShadowPainted = true Popup.dropShadowPainted = true
Popup.dropShadowInsets = -4,-4,4,4 Popup.dropShadowInsets = -4,-4,4,4
@@ -516,7 +516,7 @@ Popup.dropShadowInsets = -4,-4,4,4
PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder PopupMenu.border = com.formdev.flatlaf.ui.FlatPopupMenuBorder
PopupMenu.borderInsets = 4,1,4,1 PopupMenu.borderInsets = 4,1,4,1
PopupMenu.borderCornerRadius = $Popup.borderCornerRadius PopupMenu.borderCornerRadius = $Popup.borderCornerRadius
[mac]PopupMenu.roundedBorderWidth = $Popup.roundedBorderWidth PopupMenu.roundedBorderWidth = $Popup.roundedBorderWidth
PopupMenu.background = @menuBackground PopupMenu.background = @menuBackground
PopupMenu.scrollArrowColor = @buttonArrowColor PopupMenu.scrollArrowColor = @buttonArrowColor
@@ -564,8 +564,8 @@ RadioButtonMenuItem.background = @menuBackground
#---- RootPane ---- #---- RootPane ----
RootPane.border = com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder RootPane.border = com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder
RootPane.borderDragThickness = 6 RootPane.borderDragThickness = 5
RootPane.cornerDragWidth = 32 RootPane.cornerDragWidth = 16
RootPane.honorFrameMinimumSizeOnResize = false RootPane.honorFrameMinimumSizeOnResize = false
RootPane.honorDialogMinimumSizeOnResize = true RootPane.honorDialogMinimumSizeOnResize = true
@@ -574,12 +574,12 @@ RootPane.honorDialogMinimumSizeOnResize = true
ScrollBar.width = 10 ScrollBar.width = 10
ScrollBar.minimumButtonSize = 12,12 ScrollBar.minimumButtonSize = 12,12
ScrollBar.minimumThumbSize = 18,18 ScrollBar.minimumThumbSize = 10,10
ScrollBar.maximumThumbSize = 100000,100000 ScrollBar.maximumThumbSize = 100000,100000
ScrollBar.trackInsets = 0,0,0,0 ScrollBar.trackInsets = 0,0,0,0
ScrollBar.thumbInsets = 2,2,2,2 ScrollBar.thumbInsets = 0,0,0,0
ScrollBar.trackArc = 0 ScrollBar.trackArc = 0
ScrollBar.thumbArc = 999 ScrollBar.thumbArc = 0
ScrollBar.hoverThumbWithTrack = false ScrollBar.hoverThumbWithTrack = false
ScrollBar.pressedThumbWithTrack = false ScrollBar.pressedThumbWithTrack = false
ScrollBar.showButtons = false ScrollBar.showButtons = false
@@ -588,8 +588,15 @@ ScrollBar.buttonArrowColor = @buttonArrowColor
ScrollBar.buttonDisabledArrowColor = @buttonDisabledArrowColor ScrollBar.buttonDisabledArrowColor = @buttonDisabledArrowColor
ScrollBar.allowsAbsolutePositioning = true ScrollBar.allowsAbsolutePositioning = true
[mac]ScrollBar.minimumThumbSize = 18,18
[mac]ScrollBar.thumbInsets = 2,2,2,2
[mac]ScrollBar.thumbArc = 999
[mac]ScrollBar.hoverThumbWithTrack = true [mac]ScrollBar.hoverThumbWithTrack = true
[linux]ScrollBar.minimumThumbSize = 18,18
[linux]ScrollBar.thumbInsets = 2,2,2,2
[linux]ScrollBar.thumbArc = 999
#---- ScrollPane ---- #---- ScrollPane ----
@@ -816,14 +823,9 @@ TitlePane.iconMargins = 3,8,3,8
TitlePane.titleMargins = 3,0,3,0 TitlePane.titleMargins = 3,0,3,0
TitlePane.titleMinimumWidth = 60 TitlePane.titleMinimumWidth = 60
TitlePane.buttonSize = 44,30 TitlePane.buttonSize = 44,30
TitlePane.buttonInsets = 0,0,0,0
TitlePane.buttonArc = 0
TitlePane.buttonMinimumWidth = 30 TitlePane.buttonMinimumWidth = 30
TitlePane.buttonMaximizedHeight = 22 TitlePane.buttonMaximizedHeight = 22
TitlePane.buttonSymbolHeight = 10 TitlePane.buttonSymbolHeight = 10
TitlePane.buttonsGap = 0
TitlePane.buttonsMargins = 0,0,0,0
TitlePane.buttonsFillVertically = true
TitlePane.centerTitle = false TitlePane.centerTitle = false
TitlePane.centerTitleIfMenuBarEmbedded = true TitlePane.centerTitleIfMenuBarEmbedded = true
TitlePane.showIconBesideTitle = false TitlePane.showIconBesideTitle = false
@@ -854,27 +856,6 @@ TitlePane.small.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon, s
TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small
TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small
# Linux
[linux]TitlePane.buttonSize = 26,26
[linux]TitlePane.buttonInsets = 2,2,2,2
[linux]TitlePane.buttonArc = 999
[linux]TitlePane.buttonMaximizedHeight = -1
[linux]TitlePane.buttonSymbolHeight = 8
[linux]TitlePane.buttonsGap = 8
[linux]TitlePane.buttonsMargins = 4,4,4,4
[linux]TitlePane.buttonsFillVertically = false
[linux]TitlePane.small.buttonSize = 20,20
[linux]TitlePane.small.buttonInsets = 1,1,1,1
[linux]TitlePane.small.buttonSymbolHeight = 6
[linux]TitlePane.small.buttonsGap = 4
[linux]TitlePane.small.buttonsMargins = 2,2,2,2
[linux]TitlePane.closeBackground = $?TitlePane.buttonBackground
[linux]TitlePane.closeInactiveBackground = $?TitlePane.buttonInactiveBackground
[linux]TitlePane.closeHoverBackground = $?TitlePane.buttonHoverBackground
[linux]TitlePane.closePressedBackground = $?TitlePane.buttonPressedBackground
[linux]TitlePane.closeHoverForeground = $?TitlePane.foreground
[linux]TitlePane.closePressedForeground = $?TitlePane.foreground
#---- ToggleButton ---- #---- ToggleButton ----
@@ -932,7 +913,7 @@ ToolTipManager.enableToolTipMode = activeApplication
#---- ToolTip ---- #---- ToolTip ----
ToolTip.borderCornerRadius = $Popup.borderCornerRadius ToolTip.borderCornerRadius = $Popup.borderCornerRadius
[mac]ToolTip.roundedBorderWidth = $Popup.roundedBorderWidth ToolTip.roundedBorderWidth = $Popup.roundedBorderWidth
#---- Tree ---- #---- Tree ----

View File

@@ -36,7 +36,7 @@
@background = #f2f2f2 @background = #f2f2f2
@foreground = #000 @foreground = #000
@disabledBackground = @background @disabledBackground = @background
@disabledForeground = tint(@foreground,50%) @disabledForeground = tint(@foreground,55%)
# component background # component background
@buttonBackground = lighten(@background,5%) @buttonBackground = lighten(@background,5%)
@@ -194,8 +194,6 @@ Component.error.borderColor = lighten(desaturate($Component.error.focusedBorderC
Component.error.focusedBorderColor = #e53e4d Component.error.focusedBorderColor = #e53e4d
Component.warning.borderColor = lighten(saturate($Component.warning.focusedBorderColor,25%),20%) Component.warning.borderColor = lighten(saturate($Component.warning.focusedBorderColor,25%),20%)
Component.warning.focusedBorderColor = #e2a53a Component.warning.focusedBorderColor = #e2a53a
Component.success.borderColor = lighten(desaturate($Component.success.focusedBorderColor,20%),25%)
Component.success.focusedBorderColor = #14dc92
Component.custom.borderColor = lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse) Component.custom.borderColor = lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse)
@@ -255,6 +253,7 @@ PasswordField.revealIconColor = tint(@foreground,40%)
#---- Popup ---- #---- Popup ----
[mac]Popup.roundedBorderWidth = 0
Popup.dropShadowColor = #000 Popup.dropShadowColor = #000
Popup.dropShadowOpacity = 0.15 Popup.dropShadowOpacity = 0.15
@@ -282,7 +281,7 @@ RootPane.inactiveBorderColor = darken(@background,30%,derived)
#---- ScrollBar ---- #---- ScrollBar ----
ScrollBar.track = lighten(@background,1%,derived noAutoInverse) ScrollBar.track = lighten(@background,1%,derived noAutoInverse)
ScrollBar.thumb = darken($ScrollBar.track,15%,derived noAutoInverse) ScrollBar.thumb = darken($ScrollBar.track,10%,derived noAutoInverse)
ScrollBar.hoverTrackColor = darken($ScrollBar.track,3%,derived noAutoInverse) ScrollBar.hoverTrackColor = darken($ScrollBar.track,3%,derived noAutoInverse)
ScrollBar.hoverThumbColor = darken($ScrollBar.thumb,10%,derived noAutoInverse) ScrollBar.hoverThumbColor = darken($ScrollBar.thumb,10%,derived noAutoInverse)
ScrollBar.pressedThumbColor = darken($ScrollBar.thumb,20%,derived noAutoInverse) ScrollBar.pressedThumbColor = darken($ScrollBar.thumb,20%,derived noAutoInverse)
@@ -349,13 +348,8 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
#---- TitlePane ---- #---- TitlePane ----
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%) TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
TitlePane.buttonHoverBackground = darken($TitlePane.background,5%,derived) TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
TitlePane.buttonPressedBackground = darken($TitlePane.background,3%,derived) TitlePane.buttonPressedBackground = darken($TitlePane.background,8%,derived)
# Linux
[linux]TitlePane.buttonBackground = darken($TitlePane.background,5%,derived)
[linux]TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
[linux]TitlePane.buttonPressedBackground = darken($TitlePane.background,15%,derived)
#---- ToggleButton ---- #---- ToggleButton ----

View File

@@ -21,41 +21,27 @@
# - https://www.formdev.com/flatlaf/properties-files/ # - https://www.formdev.com/flatlaf/properties-files/
# - https://www.formdev.com/flatlaf/how-to-customize/ # - https://www.formdev.com/flatlaf/how-to-customize/
# #
# Properties in this file are applied in following order:
# 1. properties without '{...}' and without '[...]' prefix
# 2. properties specified in .theme.json file
# 3. properties starting with '{*}'
# 4. properties starting with '{*-light}' or '{*-dark}'
# 5. properties starting with '{author-<author>}',
# where '<author>' is replaced with "author" value from .theme.json file
# 6. properties starting with '{<name>---<author>}',
# where '<name>' and '<author>' are replaced with "name" and "author" values from .theme.json file
# 7. properties starting with '{<name>}',
# where '<name>' is replaced with "name" value from .theme.json file
# 8. properties with '[...]' prefix
#
#---- system colors ---- #---- system colors ----
# fix (most) system colors because they are usually not set in .json files # fix (most) system colors because they are usually not set in .json files
desktop = $TextField.background desktop = lazy(TextField.background)
activeCaptionText = $TextField.foreground activeCaptionText = lazy(TextField.foreground)
inactiveCaptionText = $TextField.foreground inactiveCaptionText = lazy(TextField.foreground)
window = $Panel.background window = lazy(Panel.background)
windowBorder = $TextField.foreground windowBorder = lazy(TextField.foreground)
windowText = $TextField.foreground windowText = lazy(TextField.foreground)
menu = $Menu.background menu = lazy(Menu.background)
menuText = $Menu.foreground menuText = lazy(Menu.foreground)
text = $TextField.background text = lazy(TextField.background)
textText = $TextField.foreground textText = lazy(TextField.foreground)
textHighlight = $TextField.selectionBackground textHighlight = lazy(TextField.selectionBackground)
textHighlightText = $TextField.selectionForeground textHighlightText = lazy(TextField.selectionForeground)
textInactiveText = $TextField.inactiveForeground textInactiveText = lazy(TextField.inactiveForeground)
control = $Panel.background control = lazy(Panel.background)
controlText = $TextField.foreground controlText = lazy(TextField.foreground)
info = $ToolTip.background info = lazy(ToolTip.background)
infoText = $ToolTip.foreground infoText = lazy(ToolTip.foreground)
#---- variables ---- #---- variables ----
@@ -63,13 +49,26 @@ infoText = $ToolTip.foreground
# make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored # make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored
@accentColor = null @accentColor = null
# use same accent color for checkmark, slider, tab underline, etc.
@accentBase2Color = @accentBaseColor
# use fixed color because it is used in borders # use fixed color because it is used in borders
@cellFocusColor = #222 @cellFocusColor = #222
#---- Button ----
Button.startBackground = $Button.background
Button.endBackground = $Button.background
Button.startBorderColor = $Button.borderColor
Button.endBorderColor = $Button.borderColor
Button.default.startBackground = $Button.default.background
Button.default.endBackground = $Button.default.background
Button.default.startBorderColor = $Button.default.borderColor
Button.default.endBorderColor = $Button.default.borderColor
Button.hoverBorderColor = null
Button.default.hoverBorderColor = null
#---- CheckBoxMenuItem ---- #---- CheckBoxMenuItem ----
# colors from intellij/checkmark.svg and darcula/checkmark.svg # colors from intellij/checkmark.svg and darcula/checkmark.svg
@@ -77,33 +76,34 @@ infoText = $ToolTip.foreground
[dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9 [dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9
#---- Component ----
Component.accentColor = lazy(ProgressBar.foreground)
#---- HelpButton ----
HelpButton.hoverBorderColor = null
#---- Slider ---- #---- Slider ----
# this "reverses" definition in FlatLightLaf/FlatDarkLaf.properties Slider.focusedColor = fade($Component.focusColor,40%,derived)
Slider.trackValueColor = $Slider.thumbColor
Slider.thumbColor = @accentSliderColor
#---- Spinner ----
# Spinner arrow button always has same colors as ComboBox arrow button
Spinner.buttonBackground = $ComboBox.buttonEditableBackground
Spinner.buttonArrowColor = $ComboBox.buttonArrowColor
Spinner.buttonDisabledArrowColor = $ComboBox.buttonDisabledArrowColor
#---- TabbedPane ---- #---- TabbedPane ----
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor() # colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
{*-light}TabbedPane.inactiveUnderlineColor = #9ca7b8 [light]TabbedPane.inactiveUnderlineColor = #9ca7b8
{*-dark}TabbedPane.inactiveUnderlineColor = #747a80 [dark]TabbedPane.inactiveUnderlineColor = #747a80
#---- ToggleButton ---- #---- ToggleButton ----
{*}ToggleButton.background = $Button.background ToggleButton.startBackground = $ToggleButton.background
{*-dark}ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived) ToggleButton.endBackground = $ToggleButton.background
{*-dark}ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived) [dark]ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived)
[dark]ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived)
#---- theme specific ---- #---- theme specific ----
@@ -112,434 +112,357 @@ Spinner.buttonDisabledArrowColor = $ComboBox.buttonDisabledArrowColor
@ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse) @ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse)
@ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse) @ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse)
@ijSeparatorLight = shade(@background,15%) @ijTextBackgroundL3 = lighten(Panel.background,3%,lazy)
@ijSeparatorDark = tint(@background,25%) @ijTextBackgroundL4 = lighten(Panel.background,4%,lazy)
@ijTextBackgroundL3 = lighten($Panel.background,3%) [Arc_Theme]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
@ijTextBackgroundL4 = lighten($Panel.background,4%) [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}@selectionInactiveForeground = @selectionForeground [Arc_Theme_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme}CheckBoxMenuItem.foreground = $MenuItem.foreground [Arc_Theme_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
{Arc_Theme}PopupMenu.foreground = $MenuItem.foreground [Arc_Theme_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme}RadioButtonMenuItem.foreground = $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_-_Orange}@selectionInactiveForeground = @selectionForeground [Arc_Theme_Dark]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground [Arc_Theme_Dark]PopupMenu.foreground = lazy(MenuItem.foreground)
{Arc_Theme_-_Orange}PopupMenu.foreground = $MenuItem.foreground [Arc_Theme_Dark]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground [Arc_Theme_Dark]ProgressBar.selectionBackground = #ddd
[Arc_Theme_Dark]ProgressBar.selectionForeground = #ddd
[Arc_Theme_Dark]ToolBar.separatorColor = lazy(Separator.foreground)
{Arc_Theme_Dark}CheckBoxMenuItem.foreground = $MenuItem.foreground [Arc_Theme_Dark_-_Orange]CheckBoxMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme_Dark}PopupMenu.foreground = $MenuItem.foreground [Arc_Theme_Dark_-_Orange]PopupMenu.foreground = lazy(MenuItem.foreground)
{Arc_Theme_Dark}RadioButtonMenuItem.foreground = $MenuItem.foreground [Arc_Theme_Dark_-_Orange]RadioButtonMenuItem.foreground = lazy(MenuItem.foreground)
{Arc_Theme_Dark}ToolBar.background = @background [Arc_Theme_Dark_-_Orange]ProgressBar.selectionBackground = #ddd
[Arc_Theme_Dark_-_Orange]ProgressBar.selectionForeground = #fff
[Arc_Theme_Dark_-_Orange]ToolBar.separatorColor = lazy(Separator.foreground)
{Arc_Theme_Dark_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground [Carbon]Table.selectionBackground = lazy(List.selectionBackground)
{Arc_Theme_Dark_-_Orange}PopupMenu.foreground = $MenuItem.foreground [Carbon]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
{Arc_Theme_Dark_-_Orange}ProgressBar.selectionForeground = #fff [Carbon]TextField.background = @ijTextBackgroundL4
{Arc_Theme_Dark_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground
{Arc_Theme_Dark_-_Orange}ToolBar.background = @background
{Carbon}Separator.foreground = @ijSeparatorDark [Cobalt_2]Component.accentColor = lazy(Component.focusColor)
{Carbon}ToolBar.separatorColor = $Separator.foreground [Cobalt_2]CheckBox.icon.background = #002946
{Carbon}Table.selectionBackground = $List.selectionBackground [Cobalt_2]CheckBox.icon.checkmarkColor = #002946
{Carbon}TextField.background = @ijTextBackgroundL4 [Cobalt_2]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
[Cobalt_2]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
[Cobalt_2]ComboBox.background = @ijTextBackgroundL3
[Cobalt_2]ComboBox.buttonBackground = @ijTextBackgroundL3
[Cobalt_2]TextField.background = @ijTextBackgroundL3
[Cobalt_2]Table.background = lazy(List.background)
[Cobalt_2]Tree.background = lazy(List.background)
{Cobalt_2}@accentBaseColor = $ColorPalette.hue3 [Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
{Cobalt_2}CheckBox.icon.background = @background [Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
{Cobalt_2}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{Cobalt_2}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{Cobalt_2}ComboBox.background = @ijTextBackgroundL3
{Cobalt_2}Slider.thumbColor = $ProgressBar.foreground
{Cobalt_2}Slider.disabledTrackColor = $Separator.foreground
{Cobalt_2}TextField.background = @ijTextBackgroundL3
{Cobalt_2}Table.background = $List.background
{Cobalt_2}Tree.background = $List.background
{Cyan_light}@disabledForeground = tint(@foreground,30%) [Dark_Flat_Theme]*.inactiveForeground = #808080
{Cyan_light}*.disabledText = @disabledForeground [Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
{Cyan_light}*.disabledForeground = @disabledForeground [Dark_Flat_Theme]TableHeader.background = #3B3B3B
{Cyan_light}*.inactiveForeground = @disabledForeground [Dark_Flat_Theme]TextPane.foreground = lazy(TextField.foreground)
{Cyan_light}Button.background = @buttonBackground [Dark_Flat_Theme]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
{Cyan_light}MenuItem.checkBackground = @ijMenuCheckBackgroundL20 [Dark_Flat_Theme]List.selectionForeground = lazy(Tree.selectionForeground)
{Cyan_light}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20 [Dark_Flat_Theme]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
[Dark_Flat_Theme]Separator.foreground = lazy(ToolBar.separatorColor)
{Dark_Flat_Theme}@accentBaseColor = $TabbedPane.underlineColor [Dark_purple]Slider.focusedColor = fade($Component.focusColor,70%,derived)
{Dark_Flat_Theme}@disabledForeground = #808080
{Dark_Flat_Theme}*.disabledText = @disabledForeground
{Dark_Flat_Theme}*.disabledForeground = @disabledForeground
{Dark_Flat_Theme}*.inactiveForeground = @disabledForeground
{Dark_Flat_Theme}TableHeader.background = #3B3B3B
{Dark_Flat_Theme}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground
{Dark_Flat_Theme}ComboBox.background = $TextField.background
{Dark_Flat_Theme}ComboBox.buttonBackground = $ComboBox.background
{Dark_Flat_Theme}List.selectionForeground = $Tree.selectionForeground
{Dark_Flat_Theme}ProgressBar.selectionForeground = @foreground
{Dark_Flat_Theme}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
{Dark_Flat_Theme}Separator.foreground = @ijSeparatorDark
{Dark_Flat_Theme}Slider.trackColor = $ProgressBar.background
{Dark_Flat_Theme}Slider.thumbColor = fade($ProgressBar.foreground,100%)
{Dark_Flat_Theme}TextPane.foreground = $TextField.foreground
{Dark_Flat_Theme}ToggleButton.foreground = $Button.foreground
{Dracula---Zihan_Ma}CheckBox.icon.background = @background [Dracula---Zihan_Ma]Component.accentColor = lazy(Component.focusColor)
{Dracula---Zihan_Ma}ComboBox.selectionBackground = $List.selectionBackground [Dracula---Zihan_Ma]ComboBox.selectionBackground = lazy(List.selectionBackground)
{Dracula---Zihan_Ma}ProgressBar.selectionBackground = #fff [Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
{Dracula---Zihan_Ma}ProgressBar.selectionForeground = #fff [Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
{Dracula---Zihan_Ma}Slider.trackColor = $?ColorPalette.selectionBackground
{Dracula---Zihan_Ma}ToggleButton.foreground = $Button.foreground
{Gradianto_Dark_Fuchsia}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 [Gradianto_Dark_Fuchsia]*.selectionBackground = #8452a7
{Gradianto_Dark_Fuchsia}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 [Gradianto_Dark_Fuchsia]*.selectionInactiveBackground = #562C6A
{Gradianto_Dark_Fuchsia}TextField.background = @ijTextBackgroundL4 [Gradianto_Dark_Fuchsia]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{Gradianto_Dark_Fuchsia}Tree.background = $List.background [Gradianto_Dark_Fuchsia]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{Gradianto_Dark_Fuchsia}Tree.selectionInactiveBackground = $List.selectionInactiveBackground [Gradianto_Dark_Fuchsia]TextField.background = @ijTextBackgroundL4
{Gradianto_Dark_Fuchsia}Separator.foreground = @ijSeparatorDark [Gradianto_Dark_Fuchsia]Tree.background = lazy(List.background)
{Gradianto_Dark_Fuchsia}ToolBar.separatorColor = $Separator.foreground [Gradianto_Dark_Fuchsia]Separator.foreground = lazy(ScrollBar.track)
{Gradianto_Dark_Fuchsia}ProgressBar.background = $ScrollBar.track [Gradianto_Dark_Fuchsia]ToolBar.separatorColor = lazy(ScrollBar.track)
{Gradianto_Dark_Fuchsia}Slider.trackColor = $ScrollBar.track [Gradianto_Dark_Fuchsia]ProgressBar.background = lazy(ScrollBar.track)
[Gradianto_Dark_Fuchsia]Slider.trackColor = lazy(ScrollBar.track)
{Gradianto_Deep_Ocean}Separator.foreground = @ijSeparatorDark [Gradianto_Deep_Ocean]TextField.background = @ijTextBackgroundL3
{Gradianto_Deep_Ocean}ToolBar.separatorColor = $Separator.foreground [Gradianto_Deep_Ocean]Tree.background = lazy(List.background)
{Gradianto_Deep_Ocean}TextField.background = @ijTextBackgroundL3
{Gradianto_Deep_Ocean}Tree.background = $List.background
{Gradianto_Midnight_Blue}ScrollBar.thumb = #533B6B [Gradianto_Midnight_Blue]ScrollBar.thumb = #533B6B
{Gradianto_Midnight_Blue}Separator.foreground = @ijSeparatorDark [Gradianto_Midnight_Blue]Table.selectionForeground = lazy(List.selectionForeground)
{Gradianto_Midnight_Blue}ToolBar.separatorColor = $Separator.foreground [Gradianto_Midnight_Blue]TextField.background = @ijTextBackgroundL4
{Gradianto_Midnight_Blue}Table.selectionForeground = $List.selectionForeground [Gradianto_Midnight_Blue]Tree.background = lazy(List.background)
{Gradianto_Midnight_Blue}TextField.background = @ijTextBackgroundL4
{Gradianto_Midnight_Blue}Tree.background = $List.background
{Gradianto_Nature_Green}Separator.foreground = @ijSeparatorDark [Gradianto_Nature_Green]Table.selectionForeground = lazy(List.selectionForeground)
{Gradianto_Nature_Green}ToolBar.separatorColor = $Separator.foreground [Gradianto_Nature_Green]TextField.background = @ijTextBackgroundL4
{Gradianto_Nature_Green}Table.selectionForeground = $List.selectionForeground
{Gradianto_Nature_Green}TextField.background = @ijTextBackgroundL4
{Gray}@disabledForeground = tint(@foreground,40%) [Gray]Separator.foreground = lazy(Slider.trackColor)
{Gray}*.disabledText = @disabledForeground [Gray]ToolBar.separatorColor = lazy(Slider.trackColor)
{Gray}*.disabledForeground = @disabledForeground
{Gray}*.inactiveForeground = @disabledForeground
{Gray}Button.background = @buttonBackground
{Gray}Separator.foreground = @ijSeparatorLight
{Gray}ToolBar.separatorColor = $Separator.foreground
{Gruvbox_Dark_Hard}@accentBaseColor = #4B6EAF [Gruvbox_Dark_Hard]Component.accentColor = lazy(TabbedPane.underlineColor)
{Gruvbox_Dark_Hard}ComboBox.background = @ijTextBackgroundL3 [Gruvbox_Dark_Hard]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
{Gruvbox_Dark_Hard}ComboBox.buttonBackground = $ComboBox.background [Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
{Gruvbox_Dark_Hard}TextField.background = @ijTextBackgroundL3 [Gruvbox_Dark_Hard]ComboBox.background = @ijTextBackgroundL3
[Gruvbox_Dark_Hard]ComboBox.buttonBackground = @ijTextBackgroundL3
[Gruvbox_Dark_Hard]TextField.background = @ijTextBackgroundL3
{Hiberbee_Dark}@disabledForeground = $ColorPalette.light3 [Gruvbox_Dark_Medium]Component.accentColor = lazy(TabbedPane.underlineColor)
{Hiberbee_Dark}*.disabledText = @disabledForeground [Gruvbox_Dark_Medium]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
{Hiberbee_Dark}*.disabledForeground = @disabledForeground [Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
{Hiberbee_Dark}*.inactiveForeground = @disabledForeground [Gruvbox_Dark_Medium]ComboBox.background = @ijTextBackgroundL3
{Hiberbee_Dark}List.selectionInactiveBackground = $Table.selectionInactiveBackground [Gruvbox_Dark_Medium]ComboBox.buttonBackground = @ijTextBackgroundL3
{Hiberbee_Dark}ProgressBar.background = $Separator.foreground [Gruvbox_Dark_Medium]TextField.background = @ijTextBackgroundL3
{Hiberbee_Dark}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
{Hiberbee_Dark}Slider.trackColor = $ColorPalette.light1
{Hiberbee_Dark}Slider.trackColor = $ColorPalette.dark10
{Hiberbee_Dark}Slider.thumbColor = @accentBaseColor
{Hiberbee_Dark}ToggleButton.foreground = $Button.foreground
{Hiberbee_Dark}ToolBar.background = @background
{High_Contrast}@accentBaseColor = $TabbedPane.underlineColor [Gruvbox_Dark_Soft]Component.accentColor = lazy(TabbedPane.underlineColor)
{High_Contrast}Slider.thumbBorderColor = $Slider.thumbColor [Gruvbox_Dark_Soft]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{High_Contrast}Slider.focusedThumbBorderColor = @background [Gruvbox_Dark_Soft]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{High_Contrast}Slider.focusedColor = $Component.focusColor [Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
{High_Contrast}Slider.focusWidth = 2 [Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
{High_Contrast}ToggleButton.selectedBackground = @selectionBackground [Gruvbox_Dark_Soft]ComboBox.background = @ijTextBackgroundL3
{High_Contrast}ToggleButton.selectedForeground = @selectionForeground [Gruvbox_Dark_Soft]ComboBox.buttonBackground = @ijTextBackgroundL3
{High_Contrast}ToggleButton.disabledSelectedBackground = shade(@selectionBackground,50%) [Gruvbox_Dark_Soft]TextField.background = @ijTextBackgroundL3
{High_Contrast}ToggleButton.toolbar.selectedBackground = @selectionBackground
{High_Contrast}[style]Button.inTextField = \ [Hiberbee_Dark]*.disabledForeground = #7F7E7D
[Hiberbee_Dark]*.disabledText = #7F7E7D
[Hiberbee_Dark]*.inactiveForeground = #7F7E7D
[Hiberbee_Dark]ProgressBar.background = lazy(Separator.foreground)
[Hiberbee_Dark]Slider.trackColor = lazy(Separator.foreground)
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
[Hiberbee_Dark]TabbedPane.selectedBackground = #434241
[Hiberbee_Dark]TabbedPane.selectedForeground = #70D7FF
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
[Hiberbee_Dark]Table.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
[Hiberbee_Dark]Tree.selectionBackground = lazy(List.selectionBackground)
[Hiberbee_Dark]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
[High_contrast]Component.accentColor = lazy(Component.focusColor)
[High_contrast]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.hoverBackground: #444; \
toolbar.pressedBackground: #666; \ toolbar.pressedBackground: #666; \
toolbar.selectedBackground: @selectionBackground toolbar.selectedBackground: #fff
[High_contrast][style]ToggleButton.inTextField = $[High_contrast][style]Button.inTextField
{Light_Flat}@accentBaseColor = $TabbedPane.underlineColor [Light_Flat]*.disabledForeground = #8C8C8C
{Light_Flat}@accentFocusColor = lighten(@accentBaseColor,15%) [Light_Flat]*.inactiveForeground = #8C8C8C
{Light_Flat}@disabledForeground = #808080 [Light_Flat]CheckBox.icon[filled].background = #fff
{Light_Flat}*.disabledText = @disabledForeground [Light_Flat]CheckBox.icon[filled].checkmarkColor = #fff
{Light_Flat}*.disabledForeground = @disabledForeground [Light_Flat]Component.accentColor = lazy(TabbedPane.underlineColor)
{Light_Flat}*.inactiveForeground = @disabledForeground [Light_Flat]ComboBox.background = lazy(ComboBox.editableBackground)
{Light_Flat}CheckBox.icon[filled].background = #fff [Light_Flat]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
{Light_Flat}CheckBox.icon[filled].checkmarkColor = #fff [Light_Flat]Separator.foreground = lazy(ToolBar.separatorColor)
{Light_Flat}ComboBox.background = $ComboBox.editableBackground [Light_Flat]TableHeader.background = #E5E5E9
{Light_Flat}ComboBox.buttonBackground = $ComboBox.background [Light_Flat]TextPane.foreground = lazy(TextField.foreground)
{Light_Flat}ProgressBar.selectionForeground = @foreground [Light_Flat]CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
{Light_Flat}Separator.foreground = @ijSeparatorLight [Light_Flat]RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground)
{Light_Flat}TableHeader.background = #E5E5E9
{Light_Flat}TextPane.foreground = $TextField.foreground
{Light_Flat}ToggleButton.foreground = $Button.foreground
{Light_Flat}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground
{Light_Flat}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground
{Monocai}@accentUnderlineColor = @accentBaseColor [Monocai]Button.default.foreground = #2D2A2F
{Monocai}*.acceleratorForeground = @menuAcceleratorForeground [Monocai]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{Monocai}*.acceleratorSelectionForeground = @menuAcceleratorSelectionForeground [Monocai]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{Monocai}Button.default.foreground = @background @Monocai.acceleratorForeground = lazy(MenuItem.disabledForeground)
{Monocai}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 @Monocai.acceleratorSelectionForeground = lighten(MenuItem.disabledForeground,10%,lazy)
{Monocai}TabbedPane.underlineColor = @accentUnderlineColor [Monocai]CheckBoxMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
{Monocai}TextField.background = @ijTextBackgroundL4 [Monocai]CheckBoxMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
@Monocai.selectionBackground = $TextField.selectionBackground [Monocai]Menu.acceleratorForeground = @Monocai.acceleratorForeground
{Monocai}ComboBox.selectionBackground = @Monocai.selectionBackground [Monocai]Menu.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
{Monocai}List.selectionBackground = @Monocai.selectionBackground [Monocai]MenuItem.acceleratorForeground = @Monocai.acceleratorForeground
{Monocai}Table.selectionBackground = @Monocai.selectionBackground [Monocai]MenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
{Monocai}Tree.selectionBackground = @Monocai.selectionBackground [Monocai]RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground
@Monocai.selectionInactiveBackground = $MenuItem.selectionBackground [Monocai]RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground
{Monocai}List.selectionInactiveBackground = @Monocai.selectionInactiveBackground [Monocai]TextField.background = @ijTextBackgroundL4
{Monocai}Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground @Monocai.selectionBackground = lazy(TextField.selectionBackground)
{Monocai}Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground [Monocai]ComboBox.selectionBackground = @Monocai.selectionBackground
[Monocai]List.selectionBackground = @Monocai.selectionBackground
[Monocai]Table.selectionBackground = @Monocai.selectionBackground
[Monocai]Tree.selectionBackground = @Monocai.selectionBackground
@Monocai.selectionInactiveBackground = lazy(MenuItem.selectionBackground)
[Monocai]List.selectionInactiveBackground = @Monocai.selectionInactiveBackground
[Monocai]Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground
[Monocai]Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground
{Monokai_Pro---Subtheme}@disabledForeground = shade(@foreground,40%) [Monokai_Pro---Subtheme]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
{Monokai_Pro---Subtheme}*.disabledText = @disabledForeground [Monokai_Pro---Subtheme]Tree.selectionBackground = lazy(List.selectionBackground)
{Monokai_Pro---Subtheme}*.disabledForeground = @disabledForeground [Monokai_Pro---Subtheme]Separator.foreground = lazy(Slider.trackColor)
{Monokai_Pro---Subtheme}*.inactiveForeground = @disabledForeground [Monokai_Pro---Subtheme]ToolBar.separatorColor = lazy(Slider.trackColor)
{Monokai_Pro---Subtheme}ProgressBar.selectionBackground = #fff
{Monokai_Pro---Subtheme}Table.selectionInactiveForeground = $List.selectionInactiveForeground
{Monokai_Pro---Subtheme}Tree.selectionBackground = $List.selectionBackground
{Monokai_Pro---Subtheme}ToggleButton.foreground = $Button.foreground
{Monokai_Pro---Subtheme}Separator.foreground = @ijSeparatorDark
{Monokai_Pro---Subtheme}ToolBar.separatorColor = $Separator.foreground
{Monokai_Pro---Subtheme}ToolBar.background = @background
{Nord}@disabledForeground = #616E88 [Nord]*.inactiveForeground = #616E88
{Nord}*.disabledText = @disabledForeground [Nord]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{Nord}*.disabledForeground = @disabledForeground [Nord]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{Nord}*.inactiveForeground = @disabledForeground [Nord]List.selectionBackground = lazy(Tree.selectionBackground)
{Nord}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 [Nord]List.selectionForeground = lazy(Tree.selectionForeground)
{Nord}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 [Nord]Table.selectionBackground = lazy(Tree.selectionBackground)
{Nord}RadioButtonMenuItem.selectionBackground = $MenuItem.selectionBackground [Nord]Table.selectionForeground = lazy(Tree.selectionForeground)
{Nord}ProgressBar.selectionBackground = @foreground [Nord]TextField.selectionBackground = lazy(Tree.selectionBackground)
{Nord}ProgressBar.selectionForeground = @background [Nord]TextField.selectionForeground = lazy(Tree.selectionForeground)
{Nord}List.selectionBackground = $Tree.selectionBackground [Nord]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
{Nord}List.selectionForeground = $Tree.selectionForeground
{Nord}Table.selectionBackground = $Tree.selectionBackground
{Nord}Table.selectionForeground = $Tree.selectionForeground
{Nord}TextField.selectionBackground = $Tree.selectionBackground
{Nord}TextField.selectionForeground = $Tree.selectionForeground
{Nord}Tree.selectionInactiveForeground = $List.selectionInactiveForeground
{NotReallyMDTheme}*.selectionInactiveBackground = #21384E [NotReallyMDTheme]*.selectionInactiveBackground = #21384E
{NotReallyMDTheme}ToolBar.separatorColor = $Separator.foreground [NotReallyMDTheme]ToolBar.separatorColor = lazy(Separator.foreground)
{One_Dark}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 [One_Dark]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
{One_Dark}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 [One_Dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{One_Dark}ProgressBar.background = $Separator.foreground [One_Dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{One_Dark}ProgressBar.selectionForeground = #fff [One_Dark]ProgressBar.background = lazy(Separator.foreground)
{One_Dark}Table.background = $Tree.background [One_Dark]Slider.trackColor = lazy(Separator.foreground)
{One_Dark}Table.selectionBackground = $Tree.selectionBackground [One_Dark]Slider.focusedColor = fade(#568af2,40%)
{One_Dark}TextField.selectionBackground = $List.selectionBackground [One_Dark]Table.background = lazy(Tree.background)
{One_Dark}Tree.selectionForeground = $List.selectionForeground [One_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
[One_Dark]TextField.selectionBackground = lazy(List.selectionBackground)
[One_Dark]Tree.selectionForeground = lazy(List.selectionForeground)
{Solarized_Dark---4lex4}@accentBaseColor = $TabbedPane.underlineColor [Solarized_Dark---4lex4]*.inactiveForeground = #657B83
{Solarized_Dark---4lex4}*.acceleratorForeground = @menuAcceleratorForeground [Solarized_Dark---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
{Solarized_Dark---4lex4}ComboBox.background = $ComboBox.editableBackground [Solarized_Dark---4lex4]ComboBox.background = lazy(ComboBox.editableBackground)
{Solarized_Dark---4lex4}ComboBox.buttonBackground = $ComboBox.editableBackground [Solarized_Dark---4lex4]ComboBox.buttonBackground = lazy(ComboBox.editableBackground)
{Solarized_Dark---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator [Solarized_Dark---4lex4]Slider.focusedColor = fade($Component.focusColor,80%,derived)
[Solarized_Dark---4lex4]ToolBar.separatorColor = lazy(Separator.foreground)
{Solarized_Light---4lex4}@accentBaseColor = $TabbedPane.underlineColor [Solarized_Light---4lex4]*.inactiveForeground = #839496
{Solarized_Light---4lex4}Slider.thumbColor = $ProgressBar.foreground [Solarized_Light---4lex4]Button.default.hoverBackground = darken($Button.default.background,3%,derived)
{Solarized_Light---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator [Solarized_Light---4lex4]Component.accentColor = lazy(TabbedPane.underlineColor)
{Spacegray}ComboBox.background = @ijTextBackgroundL4 [Spacegray]ComboBox.background = @ijTextBackgroundL4
{Spacegray}ComboBox.buttonBackground = $ComboBox.background [Spacegray]ComboBox.buttonBackground = @ijTextBackgroundL4
{Spacegray}TextField.background = @ijTextBackgroundL4 [Spacegray]TextField.background = @ijTextBackgroundL4
[Spacegray]TextField.selectionBackground = lazy(Tree.selectionBackground)
[Spacegray]TextField.selectionForeground = lazy(Tree.selectionForeground)
{vuesion-theme}@accentBaseColor = $TabbedPane.underlineColor [vuesion-theme]*.disabledForeground = #8C8C8C
{vuesion-theme}@disabledForeground = #8C8C8C [vuesion-theme]*.disabledText = #8C8C8C
{vuesion-theme}*.disabledText = @disabledForeground [vuesion-theme]*.inactiveForeground = #8C8C8C
{vuesion-theme}*.disabledForeground = @disabledForeground [vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
{vuesion-theme}*.inactiveForeground = @disabledForeground [vuesion-theme]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
{vuesion-theme}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 [vuesion-theme]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
{vuesion-theme}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 [vuesion-theme]Slider.trackValueColor = #ececee
{vuesion-theme}ProgressBar.background = #303a45 [vuesion-theme]Slider.trackColor = #303a45
{vuesion-theme}ProgressBar.foreground = #ececee [vuesion-theme]Slider.thumbColor = #ececee
{vuesion-theme}Slider.thumbColor = #ececee [vuesion-theme]Slider.focusedColor = fade(#ececee,20%)
{vuesion-theme}Slider.focusedColor = fade($Slider.thumbColor,20%) [vuesion-theme]ComboBox.background = @ijTextBackgroundL4
{vuesion-theme}ComboBox.background = @ijTextBackgroundL4 [vuesion-theme]ComboBox.buttonBackground = @ijTextBackgroundL4
{vuesion-theme}ComboBox.buttonBackground = $ComboBox.background [vuesion-theme]TextField.background = @ijTextBackgroundL4
{vuesion-theme}TextField.background = @ijTextBackgroundL4 [vuesion-theme]TextField.selectionBackground = lighten(#303A45,15%)
{vuesion-theme}TextField.selectionBackground = lighten(#303A45,15%)
{Xcode-Dark}@accentBaseColor = $List.selectionBackground [Xcode-Dark]TextField.background = @ijTextBackgroundL4
{Xcode-Dark}TextField.background = @ijTextBackgroundL4
# Material Theme UI Lite # Material Theme UI Lite
{author-Mallowigi}[light]controlHighlight = lighten($controlShadow,8%) [light][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundD10
{author-Mallowigi}[light]controlLtHighlight = lighten($controlShadow,15%) [light][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10
{author-Mallowigi}[light]controlDkShadow = darken($controlShadow,15%) [dark][author-Mallowigi]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
{author-Mallowigi}[dark]controlHighlight = darken($controlShadow,10%) [dark][author-Mallowigi]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
{author-Mallowigi}[dark]controlLtHighlight = darken($controlShadow,15%)
{author-Mallowigi}[dark]controlDkShadow = lighten($controlShadow,10%)
{author-Mallowigi}Button.hoverBorderColor = $Button.focusedBorderColor [author-Mallowigi]Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground)
{author-Mallowigi}HelpButton.hoverBorderColor = $Button.focusedBorderColor
{author-Mallowigi}[light]ToggleButton.selectedForeground = #000 [Arc_Dark]ComboBox.selectionBackground = lazy(List.selectionBackground)
{author-Mallowigi}[dark]ToggleButton.selectedForeground = #fff [Arc_Dark]Table.selectionBackground = lazy(List.selectionBackground)
{author-Mallowigi}[light]MenuItem.checkBackground = @ijMenuCheckBackgroundD10 [Atom_One_Dark]Separator.foreground = lazy(Slider.trackColor)
{author-Mallowigi}[light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10 [Atom_One_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
{author-Mallowigi}[dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
{author-Mallowigi}[dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
{author-Mallowigi}[light]Separator.foreground = @ijSeparatorLight [Atom_One_Light]List.selectionBackground = lazy(Table.selectionBackground)
{author-Mallowigi}[dark]Separator.foreground = @ijSeparatorDark [Atom_One_Light]Tree.selectionBackground = lazy(Table.selectionBackground)
{author-Mallowigi}ProgressBar.selectionBackground = @foreground [Atom_One_Light]TabbedPane.contentAreaColor = lazy(Separator.foreground)
{author-Mallowigi}TabbedPane.selectedBackground = mix(@background,$ColorPalette.table,60%)
{author-Mallowigi}ToolBar.separatorColor = $Separator.foreground
{author-Mallowigi}Button.foreground = @foreground
{author-Mallowigi}Tree.foreground = @foreground
[Dracula---Mallowigi]*.selectionBackground = #44475A
[Dracula---Mallowigi]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
[Dracula---Mallowigi]ProgressBar.selectionBackground = #fff
[Dracula---Mallowigi]ProgressBar.selectionForeground = #fff
[Dracula---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(CheckBoxMenuItem.selectionForeground)
[Dracula---Mallowigi]Table.selectionForeground = lazy(List.selectionForeground)
[Dracula---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
[Dracula---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
{Arc_Dark}ComboBox.selectionBackground = $List.selectionBackground [GitHub]ProgressBar.selectionBackground = #222
{Arc_Dark}ProgressBar.selectionBackground = #fff [GitHub]ProgressBar.selectionForeground = #222
{Arc_Dark}ProgressBar.selectionForeground = #fff [GitHub]TextField.background = @ijTextBackgroundL3
{Arc_Dark}Table.selectionBackground = $List.selectionBackground [GitHub]List.selectionBackground = lazy(Table.selectionBackground)
{Arc_Dark}Tree.selectionInactiveBackground = $List.selectionInactiveBackground [GitHub]Tree.selectionBackground = lazy(Table.selectionBackground)
{Atom_One_Dark}ProgressBar.selectionBackground = #fff [GitHub_Dark]ComboBox.selectionBackground = lazy(Tree.selectionBackground)
{Atom_One_Dark}ProgressBar.selectionForeground = #fff [GitHub_Dark]Table.selectionBackground = lazy(Tree.selectionBackground)
{Atom_One_Dark}List.selectionBackground = $Table.selectionBackground [GitHub_Dark]Separator.foreground = lazy(Slider.trackColor)
{Atom_One_Dark}Tree.selectionBackground = $Table.selectionBackground [GitHub_Dark]ToolBar.separatorColor = lazy(Slider.trackColor)
{Atom_One_Dark}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Atom_One_Dark}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Atom_One_Light}@disabledForeground = shade($ColorPalette.dis,20%) [Light_Owl]CheckBoxMenuItem.selectionForeground = lazy(CheckBoxMenuItem.foreground)
{Atom_One_Light}*.disabledText = @disabledForeground [Light_Owl]ComboBox.selectionForeground = lazy(ComboBox.foreground)
{Atom_One_Light}*.disabledForeground = @disabledForeground [Light_Owl]List.selectionInactiveForeground = lazy(List.foreground)
{Atom_One_Light}*.inactiveForeground = @disabledForeground [Light_Owl]Menu.selectionForeground = lazy(Menu.foreground)
{Atom_One_Light}TabbedPane.contentAreaColor = $Separator.foreground [Light_Owl]MenuBar.selectionForeground = lazy(MenuBar.foreground)
[Light_Owl]MenuItem.selectionForeground = lazy(MenuItem.foreground)
[Light_Owl]ProgressBar.selectionBackground = #111
[Light_Owl]ProgressBar.selectionForeground = #fff
[Light_Owl]Spinner.selectionForeground = lazy(Spinner.foreground)
[Light_Owl]Table.selectionForeground = lazy(Table.foreground)
[Light_Owl]TextField.selectionForeground = lazy(TextField.foreground)
[Light_Owl]TextField.background = @ijTextBackgroundL3
[Light_Owl]List.selectionBackground = lazy(Table.selectionBackground)
[Light_Owl]Tree.selectionBackground = lazy(Table.selectionBackground)
{Dracula---Mallowigi}ProgressBar.selectionBackground = #fff [Material_Darker]*.selectionBackground = lighten(#2D2D2D,15%)
{Dracula---Mallowigi}ProgressBar.selectionForeground = #fff [Material_Darker]Separator.foreground = lazy(Slider.trackColor)
{Dracula---Mallowigi}List.selectionBackground = $Table.selectionBackground [Material_Darker]ToolBar.separatorColor = lazy(Slider.trackColor)
{Dracula---Mallowigi}Tree.selectionBackground = $Table.selectionBackground
{Dracula---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Dracula---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{GitHub}ProgressBar.selectionBackground = #222 [Material_Deep_Ocean]*.selectionBackground = lighten(#222533,15%)
{GitHub}ProgressBar.selectionForeground = #222 [Material_Deep_Ocean]Separator.foreground = lazy(Slider.trackColor)
{GitHub}TextField.background = @ijTextBackgroundL3 [Material_Deep_Ocean]ToolBar.separatorColor = lazy(Slider.trackColor)
{GitHub}List.selectionBackground = $Table.selectionBackground
{GitHub}Tree.selectionBackground = $Table.selectionBackground
{GitHub}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{GitHub}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{GitHub_Dark}ComboBox.selectionBackground = $Tree.selectionBackground [Material_Lighter]List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground)
{GitHub_Dark}ProgressBar.selectionForeground = #fff [Material_Lighter]ProgressBar.selectionBackground = #222
{GitHub_Dark}Slider.trackColor = lighten(#2b3036,5%) [Material_Lighter]ProgressBar.selectionForeground = #fff
{GitHub_Dark}Table.selectionBackground = $Tree.selectionBackground [Material_Lighter]ComboBox.selectionBackground = lazy(List.selectionBackground)
{GitHub_Dark}Tree.selectionInactiveBackground = $Table.selectionInactiveBackground [Material_Lighter]Table.selectionBackground = lazy(List.selectionBackground)
[Material_Lighter]List.selectionForeground = lazy(Table.selectionForeground)
[Material_Lighter]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
[Material_Lighter]Tree.selectionForeground = lazy(Table.selectionForeground)
{Light_Owl}@disabledForeground = shade($ColorPalette.dis,10%) [Material_Oceanic]ProgressBar.selectionBackground = #ddd
{Light_Owl}*.disabledText = @disabledForeground [Material_Oceanic]ProgressBar.selectionForeground = #ddd
{Light_Owl}*.disabledForeground = @disabledForeground [Material_Oceanic]Separator.foreground = lazy(Slider.trackColor)
{Light_Owl}*.inactiveForeground = @disabledForeground [Material_Oceanic]ToolBar.separatorColor = lazy(Slider.trackColor)
{Light_Owl}CheckBoxMenuItem.selectionForeground = $CheckBoxMenuItem.foreground
{Light_Owl}ComboBox.selectionForeground = $ComboBox.foreground
{Light_Owl}List.selectionInactiveForeground = $Table.selectionInactiveForeground
{Light_Owl}Menu.selectionForeground = $Menu.foreground
{Light_Owl}MenuBar.selectionForeground = $MenuBar.foreground
{Light_Owl}MenuItem.selectionForeground = $MenuItem.foreground
{Light_Owl}Table.selectionForeground = $List.selectionForeground
{Light_Owl}TextField.selectionForeground = $TextField.foreground
{Light_Owl}TextField.background = @ijTextBackgroundL3
{Light_Owl}List.selectionBackground = $Table.selectionBackground
{Light_Owl}Tree.selectionBackground = $Table.selectionBackground
{Light_Owl}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Light_Owl}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Material_Darker}@disabledForeground = tint($ColorPalette.dis,30%) [Material_Palenight]ProgressBar.selectionBackground = #ddd
{Material_Darker}*.disabledText = @disabledForeground [Material_Palenight]ProgressBar.selectionForeground = #ddd
{Material_Darker}*.disabledForeground = @disabledForeground [Material_Palenight]List.selectionBackground = lazy(Table.selectionBackground)
{Material_Darker}*.inactiveForeground = @disabledForeground [Material_Palenight]Tree.selectionBackground = lazy(Table.selectionBackground)
{Material_Darker}*.selectionBackground = lighten($ColorPalette.tree,15%) [Material_Palenight]Separator.foreground = lazy(Slider.trackColor)
{Material_Darker}ProgressBar.selectionForeground = #fff [Material_Palenight]ToolBar.separatorColor = lazy(Slider.trackColor)
{Material_Darker}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Material_Deep_Ocean}@disabledForeground = tint($ColorPalette.dis,10%) [Monokai_Pro---Mallowigi]List.selectionForeground = lazy(Table.selectionForeground)
{Material_Deep_Ocean}*.disabledText = @disabledForeground [Monokai_Pro---Mallowigi]RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground)
{Material_Deep_Ocean}*.disabledForeground = @disabledForeground [Monokai_Pro---Mallowigi]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
{Material_Deep_Ocean}*.inactiveForeground = @disabledForeground [Monokai_Pro---Mallowigi]Tree.selectionForeground = lazy(Table.selectionForeground)
{Material_Deep_Ocean}*.selectionBackground = lighten($ColorPalette.tree,15%) [Monokai_Pro---Mallowigi]Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
{Material_Deep_Ocean}ProgressBar.selectionBackground = #fff [Monokai_Pro---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
{Material_Deep_Ocean}Slider.trackColor = lighten(#1A1C25,5%) [Monokai_Pro---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
{Material_Deep_Ocean}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Material_Lighter}@disabledForeground = shade($ColorPalette.dis,30%) [Moonlight]ComboBox.selectionBackground = lazy(List.selectionBackground)
{Material_Lighter}*.disabledText = @disabledForeground [Moonlight]Table.selectionBackground = lazy(List.selectionBackground)
{Material_Lighter}*.disabledForeground = @disabledForeground [Moonlight]Separator.foreground = lazy(Slider.trackColor)
{Material_Lighter}*.inactiveForeground = @disabledForeground [Moonlight]ToolBar.separatorColor = lazy(Slider.trackColor)
{Material_Lighter}ComboBox.selectionBackground = $List.selectionBackground
{Material_Lighter}List.selectionForeground = $Table.selectionForeground
{Material_Lighter}List.selectionInactiveForeground = $Table.selectionInactiveForeground
{Material_Lighter}ProgressBar.selectionBackground = #222
{Material_Lighter}RadioButtonMenuItem.selectionForeground = $Table.selectionForeground
{Material_Lighter}Table.selectionBackground = $List.selectionBackground
{Material_Lighter}Tree.selectionForeground = $Table.selectionForeground
{Material_Lighter}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Material_Oceanic}@disabledForeground = tint($ColorPalette.dis,30%) [Night_Owl]ProgressBar.selectionBackground = #ddd
{Material_Oceanic}*.disabledText = @disabledForeground [Night_Owl]ProgressBar.selectionForeground = #ddd
{Material_Oceanic}*.disabledForeground = @disabledForeground
{Material_Oceanic}*.inactiveForeground = @disabledForeground
{Material_Oceanic}ProgressBar.selectionBackground = #ddd
{Material_Oceanic}ProgressBar.selectionForeground = #ddd
{Material_Oceanic}List.selectionBackground = $Table.selectionBackground
{Material_Oceanic}Tree.selectionBackground = $Table.selectionBackground
{Material_Oceanic}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Material_Oceanic}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Material_Palenight}@disabledForeground = tint($ColorPalette.dis,20%) [Solarized_Dark---Mallowigi]ProgressBar.selectionBackground = #ccc
{Material_Palenight}*.disabledText = @disabledForeground [Solarized_Dark---Mallowigi]ProgressBar.selectionForeground = #ccc
{Material_Palenight}*.disabledForeground = @disabledForeground [Solarized_Dark---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
{Material_Palenight}*.inactiveForeground = @disabledForeground [Solarized_Dark---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
{Material_Palenight}ProgressBar.selectionBackground = #ddd
{Material_Palenight}ProgressBar.selectionForeground = #ddd
{Material_Palenight}List.selectionBackground = $Table.selectionBackground
{Material_Palenight}Tree.selectionBackground = $Table.selectionBackground
{Material_Palenight}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Material_Palenight}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Monokai_Pro---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%) [Solarized_Light---Mallowigi]ProgressBar.selectionBackground = #222
{Monokai_Pro---Mallowigi}*.disabledText = @disabledForeground [Solarized_Light---Mallowigi]ProgressBar.selectionForeground = #fff
{Monokai_Pro---Mallowigi}*.disabledForeground = @disabledForeground [Solarized_Light---Mallowigi]ComboBox.selectionBackground = lazy(List.selectionBackground)
{Monokai_Pro---Mallowigi}*.inactiveForeground = @disabledForeground [Solarized_Light---Mallowigi]Table.selectionBackground = lazy(List.selectionBackground)
{Monokai_Pro---Mallowigi}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground [Solarized_Light---Mallowigi]Separator.foreground = lazy(Slider.trackColor)
{Monokai_Pro---Mallowigi}List.selectionForeground = $Table.selectionForeground [Solarized_Light---Mallowigi]ToolBar.separatorColor = lazy(Slider.trackColor)
{Monokai_Pro---Mallowigi}Tree.selectionForeground = $Table.selectionForeground
{Monokai_Pro---Mallowigi}List.selectionInactiveForeground = $Table.selectionInactiveForeground
{Monokai_Pro---Mallowigi}List.selectionBackground = $Table.selectionBackground
{Monokai_Pro---Mallowigi}Tree.selectionBackground = $Table.selectionBackground
{Monokai_Pro---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Monokai_Pro---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
{Moonlight}ComboBox.selectionBackground = $List.selectionBackground
{Moonlight}ProgressBar.selectionForeground = #000
{Moonlight}Table.selectionBackground = $List.selectionBackground
{Moonlight}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Solarized_Dark---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%)
{Solarized_Dark---Mallowigi}*.disabledForeground = @disabledForeground
{Solarized_Dark---Mallowigi}*.inactiveForeground = @disabledForeground
{Solarized_Dark---Mallowigi}*.disabledText = @disabledForeground
{Solarized_Dark---Mallowigi}ProgressBar.selectionBackground = #ccc
{Solarized_Dark---Mallowigi}ProgressBar.selectionForeground = #ccc
{Solarized_Dark---Mallowigi}Slider.trackColor = lighten(@background,10%)
{Solarized_Dark---Mallowigi}Table.selectionBackground = $List.selectionBackground
{Solarized_Dark---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Solarized_Light---Mallowigi}@disabledForeground = tint(@foreground,30%)
{Solarized_Light---Mallowigi}*.disabledForeground = @disabledForeground
{Solarized_Light---Mallowigi}*.inactiveForeground = @disabledForeground
{Solarized_Light---Mallowigi}*.disabledText = @disabledForeground
{Solarized_Light---Mallowigi}ProgressBar.selectionBackground = #222
{Solarized_Light---Mallowigi}ComboBox.selectionBackground = $List.selectionBackground
{Solarized_Light---Mallowigi}Slider.disabledTrackColor = lighten($Slider.trackColor,5%)
{Solarized_Light---Mallowigi}Table.selectionBackground = $List.selectionBackground
{Solarized_Light---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
{Solarized_Light---Mallowigi}Button.toolbar.selectedBackground = darken($@background,15%)
{Solarized_Light---Mallowigi}ToggleButton.toolbar.selectedBackground = $Button.toolbar.selectedBackground

View File

@@ -112,7 +112,6 @@ Button.borderWidth = 0
Button.disabledBackground = darken($Button.background,10%) Button.disabledBackground = darken($Button.background,10%)
Button.default.borderWidth = 0 Button.default.borderWidth = 0
Button.default.foreground = contrast($Button.default.background, @background, @selectionForeground, 25%)
Button.toolbar.hoverBackground = #fff1 Button.toolbar.hoverBackground = #fff1
Button.toolbar.pressedBackground = #fff2 Button.toolbar.pressedBackground = #fff2
@@ -184,7 +183,6 @@ MenuBar.selectionEmbeddedInsets = 3,0,3,0
MenuBar.selectionArc = 8 MenuBar.selectionArc = 8
MenuBar.selectionBackground = lighten(@menuBackground,15%,derived) MenuBar.selectionBackground = lighten(@menuBackground,15%,derived)
MenuBar.selectionForeground = @foreground MenuBar.selectionForeground = @foreground
MenuBar.borderColor = over($Separator.foreground,$MenuBar.background)
#---- MenuItem ---- #---- MenuItem ----
@@ -295,7 +293,6 @@ TextPane.selectionForeground = @textSelectionForeground
ToggleButton.disabledBackground = $Button.disabledBackground ToggleButton.disabledBackground = $Button.disabledBackground
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived) ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
ToggleButton.selectedForeground = lighten($ToggleButton.foreground,20%)
ToggleButton.toolbar.selectedBackground = #fff3 ToggleButton.toolbar.selectedBackground = #fff3

View File

@@ -79,7 +79,7 @@
# general background and foreground (text color) # general background and foreground (text color)
@background = #f6f6f6 @background = #f6f6f6
@foreground = over(@nsControlTextColor,@background) @foreground = over(@nsControlTextColor,@background)
@disabledForeground = over(@nsSecondaryLabelColor,@background) @disabledForeground = over(@nsTertiaryLabelColor,@background)
# component background # component background
@buttonBackground = @nsControlColor @buttonBackground = @nsControlColor
@@ -184,7 +184,6 @@ MenuBar.selectionEmbeddedInsets = 3,0,3,0
MenuBar.selectionArc = 8 MenuBar.selectionArc = 8
MenuBar.selectionBackground = darken(@menuBackground,15%,derived) MenuBar.selectionBackground = darken(@menuBackground,15%,derived)
MenuBar.selectionForeground = @foreground MenuBar.selectionForeground = @foreground
MenuBar.borderColor = over($Separator.foreground,$MenuBar.background)
#---- MenuItem ---- #---- MenuItem ----

View File

@@ -17,9 +17,6 @@
package com.formdev.flatlaf; package com.formdev.flatlaf;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
@@ -30,16 +27,8 @@ import javax.swing.border.Border;
import javax.swing.UIDefaults.ActiveValue; import javax.swing.UIDefaults.ActiveValue;
import javax.swing.UIDefaults.LazyValue; import javax.swing.UIDefaults.LazyValue;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import com.formdev.flatlaf.ui.FlatEmptyBorder; import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder; import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
import com.formdev.flatlaf.util.ColorFunctions.Fade;
import com.formdev.flatlaf.util.ColorFunctions.HSLChange;
import com.formdev.flatlaf.util.ColorFunctions.HSLIncreaseDecrease;
import com.formdev.flatlaf.util.ColorFunctions.Mix;
import com.formdev.flatlaf.util.ColorFunctions.Mix2;
/** /**
* @author Karl Tauber * @author Karl Tauber
@@ -191,336 +180,6 @@ public class TestUIDefaultsLoader
assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) ); assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) );
} }
@Test
void parseColorFunctions() {
// lighten
assertEquals( new Color( 0xff6666 ), parseColor( "lighten(#f00, 20%)" ) );
assertEquals( new Color( 0xff3333 ), parseColor( "lighten(#f00, 20%, relative)" ) );
assertEquals( new Color( 0xaaaaaa ), parseColor( "lighten(#ddd, 20%, autoInverse)" ) );
assertEquals( new Color( 0xb1b1b1 ), parseColor( "lighten(#ddd, 20%, relative autoInverse)" ) );
// darken
assertEquals( new Color( 0x990000 ), parseColor( "darken(#f00, 20%)" ) );
assertEquals( new Color( 0xcc0000 ), parseColor( "darken(#f00, 20%, relative)" ) );
assertEquals( new Color( 0x555555 ), parseColor( "darken(#222, 20%, autoInverse)" ) );
assertEquals( new Color( 0x292929 ), parseColor( "darken(#222, 20%, relative autoInverse)" ) );
// saturate
assertEquals( new Color( 0xf32e2e ), parseColor( "saturate(#d44, 20%)" ) );
assertEquals( new Color( 0xec3535 ), parseColor( "saturate(#d44, 20%, relative)" ) );
assertEquals( new Color( 0xc75a5a ), parseColor( "saturate(#d44, 20%, autoInverse)" ) );
assertEquals( new Color( 0xce5353 ), parseColor( "saturate(#d44, 20%, relative autoInverse)" ) );
// desaturate
assertEquals( new Color( 0x745858 ), parseColor( "desaturate(#844, 20%)" ) );
assertEquals( new Color( 0x814b4b ), parseColor( "desaturate(#844, 20%, relative)" ) );
assertEquals( new Color( 0x9c3030 ), parseColor( "desaturate(#844, 20%, autoInverse)" ) );
assertEquals( new Color( 0x8f3d3d ), parseColor( "desaturate(#844, 20%, relative autoInverse)" ) );
// fadein
assertEquals( new Color( 0xddff0000, true ), parseColor( "fadein(#f00a, 20%)" ) );
assertEquals( new Color( 0xccff0000, true ), parseColor( "fadein(#f00a, 20%, relative)" ) );
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadein(#f00a, 20%, autoInverse)" ) );
assertEquals( new Color( 0x88ff0000, true ), parseColor( "fadein(#f00a, 20%, relative autoInverse)" ) );
// fadeout
assertEquals( new Color( 0x11ff0000, true ), parseColor( "fadeout(#f004, 20%)" ) );
assertEquals( new Color( 0x36ff0000, true ), parseColor( "fadeout(#f004, 20%, relative)" ) );
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadeout(#f004, 20%, autoInverse)" ) );
assertEquals( new Color( 0x52ff0000, true ), parseColor( "fadeout(#f004, 20%, relative autoInverse)" ) );
// fade
assertEquals( new Color( 0x33ff0000, true ), parseColor( "fade(#f00, 20%)" ) );
assertEquals( new Color( 0xccff0000, true ), parseColor( "fade(#ff000010, 80%)" ) );
// spin
assertEquals( new Color( 0xffaa00 ), parseColor( "spin(#f00, 40)" ) );
assertEquals( new Color( 0xff00aa ), parseColor( "spin(#f00, -40)" ) );
// changeHue / changeSaturation / changeLightness / changeAlpha
assertEquals( new Color( 0xffaa00 ), parseColor( "changeHue(#f00, 40)" ) );
assertEquals( new Color( 0xb34d4d ), parseColor( "changeSaturation(#f00, 40%)" ) );
assertEquals( new Color( 0xcc0000 ), parseColor( "changeLightness(#f00, 40%)" ) );
assertEquals( new Color( 0x66ff0000, true ), parseColor( "changeAlpha(#f00, 40%)" ) );
// mix
assertEquals( new Color( 0x808000 ), parseColor( "mix(#f00, #0f0)" ) );
assertEquals( new Color( 0xbf4000 ), parseColor( "mix(#f00, #0f0, 75%)" ) );
// tint
assertEquals( new Color( 0xff80ff ), parseColor( "tint(#f0f)" ) );
assertEquals( new Color( 0xffbfff ), parseColor( "tint(#f0f, 75%)" ) );
// shade
assertEquals( new Color( 0x800080 ), parseColor( "shade(#f0f)" ) );
assertEquals( new Color( 0x400040 ), parseColor( "shade(#f0f, 75%)" ) );
// contrast
assertEquals( new Color( 0x0000ff ), parseColor( "contrast(#bbb, #00f, #0f0)" ) );
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#444, #00f, #0f0)" ) );
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#bbb, #00f, #0f0, 60%)" ) );
// rgb / rgba
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
assertEquals( new Color( 0x197fb2 ), parseColor( "rgb(10%,50%,70%)" ) );
assertEquals( new Color( 0x197f46 ), parseColor( "rgb(10%,50%,70)" ) );
assertEquals( new Color( 0x405a8120, true ), parseColor( "rgba(90, 129, 32, 64)" ) );
assertEquals( new Color( 0x335a8120, true ), parseColor( "rgba(90, 129, 32, 20%)" ) );
// hsl / hsla
assertEquals( new Color( 0x7fff00 ), parseColor( "hsl(90, 100%, 50%)" ) );
assertEquals( new Color( 0x337fff00, true ), parseColor( "hsla(90, 100%, 50%, 20%)" ) );
}
@Test
void parseLazyColorFunctions() {
// lighten
assertEquals( new Color( 0xff6666 ), parseColorLazy( "lighten(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
// darken
assertEquals( new Color( 0x990000 ), parseColorLazy( "darken(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
// saturate
assertEquals( new Color( 0xf32e2e ), parseColorLazy( "saturate(dummyColor, 20%, lazy)", new Color( 0xdd4444 ) ) );
// desaturate
assertEquals( new Color( 0x745858 ), parseColorLazy( "desaturate(dummyColor, 20%, lazy)", new Color( 0x884444 ) ) );
// fadein
assertEquals( new Color( 0xddff0000, true ), parseColorLazy( "fadein(dummyColor, 20%, lazy)", new Color( 0xaaff0000, true ) ) );
// fadeout
assertEquals( new Color( 0x11ff0000, true ), parseColorLazy( "fadeout(dummyColor, 20%, lazy)", new Color( 0x44ff0000, true ) ) );
// fade
assertEquals( new Color( 0x33ff0000, true ), parseColorLazy( "fade(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
assertEquals( new Color( 0xccff0000, true ), parseColorLazy( "fade(dummyColor, 80%, lazy)", new Color( 0x10ff0000, true ) ) );
// spin
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "spin(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
assertEquals( new Color( 0xff00aa ), parseColorLazy( "spin(dummyColor, -40, lazy)", new Color( 0xff0000 ) ) );
// changeHue / changeSaturation / changeLightness / changeAlpha
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "changeHue(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
assertEquals( new Color( 0xb34d4d ), parseColorLazy( "changeSaturation(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
assertEquals( new Color( 0xcc0000 ), parseColorLazy( "changeLightness(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
assertEquals( new Color( 0x66ff0000, true ), parseColorLazy( "changeAlpha(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
// mix
assertEquals( new Color( 0x808000 ), parseColorLazy( "mix(#f00, dummyColor, lazy)", new Color( 0x00ff00 ) ) );
assertEquals( new Color( 0xbf4000 ), parseColorLazy( "mix(#f00, dummyColor, 75%, lazy)", new Color( 0x00ff00 ) ) );
// tint
assertEquals( new Color( 0xff80ff ), parseColorLazy( "tint(dummyColor, lazy)", new Color( 0xff00ff ) ) );
assertEquals( new Color( 0xffbfff ), parseColorLazy( "tint(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
// shade
assertEquals( new Color( 0x800080 ), parseColorLazy( "shade(dummyColor, lazy)", new Color( 0xff00ff ) ) );
assertEquals( new Color( 0x400040 ), parseColorLazy( "shade(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
}
@Test
void parseDerivedColorFunctions() {
// mix
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( Color.red, 50 ) );
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( Color.red, 75 ) );
// tint
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( Color.white, 50 ) );
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( Color.white, 75 ) );
// shade
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( Color.black, 50 ) );
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( Color.black, 75 ) );
// lighten
assertDerivedColorEquals( new Color( 0xff6666 ), "lighten(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, true, 20, false, true ) );
assertDerivedColorEquals( new Color( 0xff3333 ), "lighten(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, true, 20, true, true ) );
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, false, false ) );
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, true, false ) );
// darken
assertDerivedColorEquals( new Color( 0x990000 ), "darken(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, false, 20, false, true ) );
assertDerivedColorEquals( new Color( 0xcc0000 ), "darken(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, false, 20, true, true ) );
assertDerivedColorEquals( new Color( 0x000000 ), "darken(#222, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, false, false ) );
assertDerivedColorEquals( new Color( 0x1b1b1b ), "darken(#222, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, true, false ) );
// saturate
assertDerivedColorEquals( new Color( 0xc75a5a ), "saturate(#d44, 20%, derived)", new HSLIncreaseDecrease( 1, true, 20, false, true ) );
assertDerivedColorEquals( new Color( 0xce5353 ), "saturate(#d44, 20%, derived relative)", new HSLIncreaseDecrease( 1, true, 20, true, true ) );
assertDerivedColorEquals( new Color( 0xf32e2e ), "saturate(#d44, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, false, false ) );
assertDerivedColorEquals( new Color( 0xec3535 ), "saturate(#d44, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, true, false ) );
// desaturate
assertDerivedColorEquals( new Color( 0x9c3030 ), "desaturate(#844, 20%, derived)", new HSLIncreaseDecrease( 1, false, 20, false, true ) );
assertDerivedColorEquals( new Color( 0x8f3d3d ), "desaturate(#844, 20%, derived relative)", new HSLIncreaseDecrease( 1, false, 20, true, true ) );
assertDerivedColorEquals( new Color( 0x745858 ), "desaturate(#844, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, false, false ) );
assertDerivedColorEquals( new Color( 0x814b4b ), "desaturate(#844, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, true, false ) );
// fadein
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadein(#f00a, 20%, derived)", new HSLIncreaseDecrease( 3, true, 20, false, true ) );
assertDerivedColorEquals( new Color( 0x88ff0000, true ), "fadein(#f00a, 20%, derived relative)", new HSLIncreaseDecrease( 3, true, 20, true, true ) );
assertDerivedColorEquals( new Color( 0xddff0000, true ), "fadein(#f00a, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, false, false ) );
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fadein(#f00a, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, true, false ) );
// fadeout
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadeout(#f004, 20%, derived)", new HSLIncreaseDecrease( 3, false, 20, false, true ) );
assertDerivedColorEquals( new Color( 0x52ff0000, true ), "fadeout(#f004, 20%, derived relative)", new HSLIncreaseDecrease( 3, false, 20, true, true ) );
assertDerivedColorEquals( new Color( 0x11ff0000, true ), "fadeout(#f004, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, false, false ) );
assertDerivedColorEquals( new Color( 0x36ff0000, true ), "fadeout(#f004, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, true, false ) );
// fade
assertDerivedColorEquals( new Color( 0x33ff0000, true ), "fade(#f00, 20%, derived)", new Fade( 20 ) );
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fade(#ff000010, 80%, derived)", new Fade( 80 ) );
// spin
assertDerivedColorEquals( new Color( 0xffaa00 ), "spin(#f00, 40, derived)", new HSLIncreaseDecrease( 0, true, 40, false, false ) );
assertDerivedColorEquals( new Color( 0xff00aa ), "spin(#f00, -40, derived)", new HSLIncreaseDecrease( 0, true, -40, false, false ) );
// changeHue / changeSaturation / changeLightness / changeAlpha
assertDerivedColorEquals( new Color( 0xffaa00 ), "changeHue(#f00, 40, derived)", new HSLChange( 0, 40 ) );
assertDerivedColorEquals( new Color( 0xb34d4d ), "changeSaturation(#f00, 40%, derived)", new HSLChange( 1, 40 ) );
assertDerivedColorEquals( new Color( 0xcc0000 ), "changeLightness(#f00, 40%, derived)", new HSLChange( 2, 40 ) );
assertDerivedColorEquals( new Color( 0x66ff0000, true ), "changeAlpha(#f00, 40%, derived)", new HSLChange( 3, 40 ) );
// mix
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( new Color( 0xff0000 ), 50 ) );
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( new Color( 0xff0000 ), 75 ) );
// tint
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( new Color( 0xffffff ), 50 ) );
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( new Color( 0xffffff ), 75 ) );
// shade
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( new Color( 0x000000 ), 50 ) );
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( new Color( 0x000000 ), 75 ) );
}
private void assertDerivedColorEquals( Color expectedColor, String actualStyle, ColorFunction... expectedFunctions ) {
Object actual = parseColor( actualStyle );
assertInstanceOf( DerivedColor.class, actual );
assertEquals( expectedColor, actual );
ColorFunction[] actualFunctions = ((DerivedColor)actual).getFunctions();
assertEquals( expectedFunctions.length, actualFunctions.length );
for( int i = 0; i < expectedFunctions.length; i++ )
assertColorFunctionEquals( expectedFunctions[i], actualFunctions[i] );
}
private void assertColorFunctionEquals( ColorFunction expected, ColorFunction actual ) {
assertEquals( expected.getClass(), actual.getClass() );
if( expected instanceof HSLIncreaseDecrease ) {
HSLIncreaseDecrease e = (HSLIncreaseDecrease) expected;
HSLIncreaseDecrease a = (HSLIncreaseDecrease) actual;
assertEquals( e.hslIndex, a.hslIndex );
assertEquals( e.increase, a.increase );
assertEquals( e.amount, a.amount );
assertEquals( e.relative, a.relative );
assertEquals( e.autoInverse, a.autoInverse );
} else if( expected instanceof HSLChange ) {
HSLChange e = (HSLChange) expected;
HSLChange a = (HSLChange) actual;
assertEquals( e.hslIndex, a.hslIndex );
assertEquals( e.value, a.value );
} else if( expected instanceof Fade ) {
Fade e = (Fade) expected;
Fade a = (Fade) actual;
assertEquals( e.amount, a.amount );
} else if( expected instanceof Mix ) {
Mix e = (Mix) expected;
Mix a = (Mix) actual;
assertEquals( e.color2, a.color2 );
assertEquals( e.weight, a.weight );
} else if( expected instanceof Mix2 ) {
Mix2 e = (Mix2) expected;
Mix2 a = (Mix2) actual;
assertEquals( e.color1, a.color1 );
assertEquals( e.weight, a.weight );
} else
assertTrue( false );
}
private Object parseColor( String value ) {
return UIDefaultsLoader.parseValue( "dummyColor", value, null );
}
private Object parseColorLazy( String value, Color actual ) {
UIManager.put( "dummyColor", actual );
Object v = UIDefaultsLoader.parseValue( "dummyColor", value, null );
assertInstanceOf( LazyValue.class, v );
return ((LazyValue)v).createValue( null );
}
//---- invalid values -----------------------------------------------------
@Test
void parseInvalidValue() {
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", null ) );
assertThrows( new NumberFormatException( "invalid integer or float '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", null ) );
assertThrows( new NumberFormatException( "invalid integer or float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", null ) );
assertThrows( new IllegalArgumentException( "invalid insets '1,abc,3,4'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,abc,3,4", null ) );
assertThrows( new IllegalArgumentException( "invalid insets '1,2,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3", null ) );
assertThrows( new IllegalArgumentException( "invalid size '1abc'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1abc", null ) );
assertThrows( new IllegalArgumentException( "invalid size '1'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1", null ) );
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummy", "#f0", null ) );
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummyColor", "#f0", null ) );
}
@Test
void parseInvalidValueWithJavaType() {
assertThrows( new IllegalArgumentException( "invalid boolean 'falseyy'" ), () -> UIDefaultsLoader.parseValue( "dummy", "falseyy", boolean.class ) );
assertThrows( new IllegalArgumentException( "invalid boolean 'falseyy'" ), () -> UIDefaultsLoader.parseValue( "dummy", "falseyy", Boolean.class ) );
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", char.class ) );
assertThrows( new IllegalArgumentException( "invalid character 'abc'" ), () -> UIDefaultsLoader.parseValue( "dummyChar", "abc", Character.class ) );
assertThrows( new NumberFormatException( "invalid integer '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", int.class ) );
assertThrows( new NumberFormatException( "invalid integer '123abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "123abc", Integer.class ) );
assertThrows( new NumberFormatException( "invalid float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", float.class ) );
assertThrows( new NumberFormatException( "invalid float '1.23abc'" ), () -> UIDefaultsLoader.parseValue( "dummyWidth", "1.23abc", Float.class ) );
assertThrows( new IllegalArgumentException( "invalid insets '1,abc,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,abc,3", Insets.class ) );
assertThrows( new IllegalArgumentException( "invalid insets '1,2,3'" ), () -> UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3", Insets.class ) );
assertThrows( new IllegalArgumentException( "invalid size '1abc'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1abc", Dimension.class ) );
assertThrows( new IllegalArgumentException( "invalid size '1'" ), () -> UIDefaultsLoader.parseValue( "dummySize", "1", Dimension.class ) );
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummy", "#f0", Color.class ) );
assertThrows( new IllegalArgumentException( "invalid color '#f0'" ), () -> UIDefaultsLoader.parseValue( "dummyColor", "#f0", Color.class ) );
}
@Test
void parseInvalidBorders() {
assertThrows( new IllegalArgumentException( "invalid border '1,abc,3,4' (invalid insets '1,abc,3,4')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,abc,3,4", null ) );
assertThrows( new IllegalArgumentException( "invalid border '1,2,3' (invalid insets '1,2,3')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3", null ) );
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,,,' (invalid insets '1,2,3,,,')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,,,", null ) );
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f0' (invalid color '#f0')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f0", null ) );
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f00,2.5abc' (invalid float '2.5abc')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f00,2.5abc", null ) );
assertThrows( new IllegalArgumentException( "invalid border '1,2,3,4,#f00,2.5,6abc' (invalid integer '6abc')" ), () -> UIDefaultsLoader.parseValue( "dummyBorder", "1,2,3,4,#f00,2.5,6abc", null ) );
}
@Test
void parseInvalidFonts() {
// size
assertThrows( new IllegalArgumentException( "invalid font '12abc' (invalid integer '12abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "12abc", null ) );
assertThrows( new IllegalArgumentException( "invalid font '+12abc' (invalid integer '+12abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+12abc", null ) );
assertThrows( new IllegalArgumentException( "invalid font '+3abc' (invalid integer '+3abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+3abc", null ) );
assertThrows( new IllegalArgumentException( "invalid font '-4abc' (invalid integer '-4abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "-4abc", null ) );
assertThrows( new IllegalArgumentException( "invalid font '150abc%' (invalid integer '150abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "150abc%", null ) );
assertThrows( new IllegalArgumentException( "invalid font 'bold 13abc Monospaced' (invalid integer '13abc')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "bold 13abc Monospaced", null ) );
// invalid combinations of styles
assertThrows( new IllegalArgumentException( "invalid font 'bold +italic': can not mix absolute style (e.g. 'bold') with derived style (e.g. '+italic')" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "bold +italic", null ) );
assertThrows( new IllegalArgumentException( "invalid font '+bold -bold': can not use '+bold' and '-bold'" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+bold -bold", null ) );
assertThrows( new IllegalArgumentException( "invalid font '+italic -italic': can not use '+italic' and '-italic'" ), () -> UIDefaultsLoader.parseValue( "dummyFont", "+italic -italic", null ) );
}
private void assertThrows( Throwable expected, Executable executable ) {
Throwable actual = assertThrowsExactly( expected.getClass(), executable );
assertEquals( expected.getMessage(), actual.getMessage() );
}
//---- class TestInstance ------------------------------------------------- //---- class TestInstance -------------------------------------------------
@SuppressWarnings( "EqualsHashCode" ) // Error Prone @SuppressWarnings( "EqualsHashCode" ) // Error Prone

View File

@@ -1,404 +0,0 @@
/*
* Copyright 2025 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.ui;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.awt.Color;
import java.util.HashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JRootPane;
import javax.swing.UIManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
/**
* @author Karl Tauber
*/
public class TestFlatButton
{
@BeforeAll
static void setup() {
String[] defs = {
"Button.background", "#000001",
"Button.foreground", "#000002",
"Button.focusedBackground", "#000003",
"Button.focusedForeground", "#000004",
"Button.hoverBackground", "#000005",
"Button.hoverForeground", "#000006",
"Button.pressedBackground", "#000007",
"Button.pressedForeground", "#000008",
"Button.selectedBackground", "#000009",
"Button.selectedForeground", "#00000a",
"Button.disabledBackground", "#00000b",
"Button.disabledText", "#00000c",
"Button.disabledSelectedBackground", "#00000d",
"Button.disabledSelectedForeground", "#00000e",
"Button.default.background", "#000101",
"Button.default.foreground", "#000102",
"Button.default.focusedBackground", "#000103",
"Button.default.focusedForeground", "#000104",
"Button.default.hoverBackground", "#000105",
"Button.default.hoverForeground", "#000106",
"Button.default.pressedBackground", "#000107",
"Button.default.pressedForeground", "#000108",
"Button.toolbar.hoverBackground", "#000201",
"Button.toolbar.hoverForeground", "#000202",
"Button.toolbar.pressedBackground", "#000203",
"Button.toolbar.pressedForeground", "#000204",
"Button.toolbar.selectedBackground", "#000205",
"Button.toolbar.selectedForeground", "#000206",
"Button.toolbar.disabledSelectedBackground", "#000207",
"Button.toolbar.disabledSelectedForeground", "#000208",
};
HashMap<String, String> globalExtraDefaults = new HashMap<>();
for( int i = 0; i < defs.length; i += 2 )
globalExtraDefaults.put( defs[i], defs[i+1] );
FlatLaf.setGlobalExtraDefaults( globalExtraDefaults );
TestUtils.setup( false );
}
@AfterAll
static void cleanup() {
TestUtils.cleanup();
}
@Test
void background() {
JButton b = new JButton();
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
UIManager.getColor( "Button.background" ),
UIManager.getColor( "Button.disabledBackground" ),
UIManager.getColor( "Button.focusedBackground" ),
UIManager.getColor( "Button.hoverBackground" ),
UIManager.getColor( "Button.pressedBackground" ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
UIManager.getColor( "Button.selectedBackground" ),
UIManager.getColor( "Button.disabledSelectedBackground" ),
null,
null,
UIManager.getColor( "Button.pressedBackground" ) );
b.setSelected( false );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
UIManager.getColor( "Button.default.background" ),
UIManager.getColor( "Button.disabledBackground" ),
UIManager.getColor( "Button.default.focusedBackground" ),
UIManager.getColor( "Button.default.hoverBackground" ),
UIManager.getColor( "Button.default.pressedBackground" ) );
rootPane.getContentPane().remove( b );
}
@Test
void foreground() {
JButton b = new JButton();
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
UIManager.getColor( "Button.foreground" ),
UIManager.getColor( "Button.disabledText" ),
UIManager.getColor( "Button.focusedForeground" ),
UIManager.getColor( "Button.hoverForeground" ),
UIManager.getColor( "Button.pressedForeground" ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
UIManager.getColor( "Button.selectedForeground" ),
FlatUIUtils.getUIColor( "Button.disabledSelectedForeground", "Button.disabledText" ),
null,
null,
UIManager.getColor( "Button.pressedForeground" ) );
b.setSelected( false );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
UIManager.getColor( "Button.default.foreground" ),
UIManager.getColor( "Button.disabledText" ),
UIManager.getColor( "Button.default.focusedForeground" ),
UIManager.getColor( "Button.default.hoverForeground" ),
UIManager.getColor( "Button.default.pressedForeground" ) );
rootPane.getContentPane().remove( b );
}
@Test
void backgroundExplicit() {
JButton b = new JButton();
Color c = new Color( 0x020001 );
b.setBackground( c );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
c,
UIManager.getColor( "Button.disabledBackground" ),
null,
UIManager.getColor( "Button.hoverBackground" ),
UIManager.getColor( "Button.pressedBackground" ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
UIManager.getColor( "Button.selectedBackground" ),
UIManager.getColor( "Button.disabledSelectedBackground" ),
null,
null,
UIManager.getColor( "Button.pressedBackground" ) );
b.setSelected( false );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
c,
UIManager.getColor( "Button.disabledBackground" ),
null,
UIManager.getColor( "Button.default.hoverBackground" ),
UIManager.getColor( "Button.default.pressedBackground" ) );
rootPane.getContentPane().remove( b );
}
@Test
void foregroundExplicit() {
JButton b = new JButton();
Color c = new Color( 0x020001 );
b.setForeground( c );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
c,
UIManager.getColor( "Button.disabledText" ),
null,
UIManager.getColor( "Button.hoverForeground" ),
UIManager.getColor( "Button.pressedForeground" ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
c,
FlatUIUtils.getUIColor( "Button.disabledSelectedForeground", "Button.disabledText" ),
null,
null,
UIManager.getColor( "Button.pressedForeground" ) );
b.setSelected( false );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
c,
UIManager.getColor( "Button.disabledText" ),
null,
UIManager.getColor( "Button.default.hoverForeground" ),
UIManager.getColor( "Button.default.pressedForeground" ) );
rootPane.getContentPane().remove( b );
}
@Test
void backgroundStyled() {
JButton b = new JButton();
b.putClientProperty( FlatClientProperties.STYLE,
"background: #020001;" +
"disabledBackground: #020002;" +
"focusedBackground: #020003;" +
"hoverBackground: #020004;" +
"pressedBackground: #020005;" +
"selectedBackground: #020006;" +
"disabledSelectedBackground: #020007;" );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
new Color( 0x020001 ),
new Color( 0x020002 ),
new Color( 0x020003 ),
new Color( 0x020004 ),
new Color( 0x020005 ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
new Color( 0x020006 ),
new Color( 0x020007 ),
null,
null,
new Color( 0x020005 ) );
b.setSelected( false );
Color c = new Color( 0x0a0001 );
b.setBackground( c );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
c,
new Color( 0x020002 ),
c,
new Color( 0x020004 ),
new Color( 0x020005 ) );
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
new Color( 0x020006 ),
new Color( 0x020007 ),
null,
null,
new Color( 0x020005 ) );
b.setSelected( false );
b = new JButton();
b.putClientProperty( FlatClientProperties.STYLE,
"default.background: #020101;" +
"disabledBackground: #020102;" +
"default.focusedBackground: #020103;" +
"default.hoverBackground: #020104;" +
"default.pressedBackground: #020105;" );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getBackground( b2 ),
new Color( 0x020101 ),
new Color( 0x020102 ),
new Color( 0x020103 ),
new Color( 0x020104 ),
new Color( 0x020105 ) );
rootPane.getContentPane().remove( b );
}
@Test
void foregroundStyled() {
JButton b = new JButton();
b.putClientProperty( FlatClientProperties.STYLE,
"foreground: #020001;" +
"disabledText: #020002;" +
"focusedForeground: #020003;" +
"hoverForeground: #020004;" +
"pressedForeground: #020005;" +
"selectedForeground: #020006;" +
"disabledSelectedForeground: #020007;" );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
new Color( 0x020001 ),
new Color( 0x020002 ),
new Color( 0x020003 ),
new Color( 0x020004 ),
new Color( 0x020005 ) );
// selected
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
new Color( 0x020006 ),
new Color( 0x020007 ),
null,
null,
new Color( 0x020005 ) );
b.setSelected( false );
Color c = new Color( 0x0a0001 );
b.setForeground( c );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
c,
new Color( 0x020002 ),
c,
new Color( 0x020004 ),
new Color( 0x020005 ) );
b.setSelected( true );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
c,
new Color( 0x020007 ),
null,
null,
new Color( 0x020005 ) );
b.setSelected( false );
b = new JButton();
b.putClientProperty( FlatClientProperties.STYLE,
"default.foreground: #020101;" +
"disabledText: #020102;" +
"default.focusedForeground: #020103;" +
"default.hoverForeground: #020104;" +
"default.pressedForeground: #020105;" );
// default
JRootPane rootPane = new JRootPane();
rootPane.getContentPane().add( b );
rootPane.setDefaultButton( b );
testButtonColors( b, b2 -> ((FlatButtonUI)b2.getUI()).getForeground( b2 ),
new Color( 0x020101 ),
new Color( 0x020102 ),
new Color( 0x020103 ),
new Color( 0x020104 ),
new Color( 0x020105 ) );
rootPane.getContentPane().remove( b );
}
private void testButtonColors( JButton b, Function<JButton, Color> f,
Color expectedEnabled, Color expectedDisabled, Color expectedFocused,
Color expectedHover, Color expectedPressed
)
{
assertEquals( expectedEnabled, f.apply( b ) );
// disabled
b.setEnabled( false );
assertEquals( expectedDisabled, f.apply( b ) );
b.setEnabled( true );
// focused
if( expectedFocused != null ) {
b.putClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER, (Predicate<JComponent>) c -> true );
assertEquals( expectedFocused, f.apply( b ) );
b.putClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER, null );
}
// hover
if( expectedHover != null ) {
b.getModel().setRollover( true );
assertEquals( expectedHover, f.apply( b ) );
b.getModel().setRollover( false );
}
// pressed
if( expectedPressed != null ) {
b.getModel().setPressed( true );
assertEquals( expectedPressed, f.apply( b ) );
b.getModel().setPressed( false );
}
}
}

View File

@@ -1080,8 +1080,6 @@ public class TestFlatStyleableInfo
"error.focusedBorderColor", Color.class, "error.focusedBorderColor", Color.class,
"warning.borderColor", Color.class, "warning.borderColor", Color.class,
"warning.focusedBorderColor", Color.class, "warning.focusedBorderColor", Color.class,
"success.borderColor", Color.class,
"success.focusedBorderColor", Color.class,
"custom.borderColor", Color.class, "custom.borderColor", Color.class,
"outline", String.class, "outline", String.class,

View File

@@ -1024,8 +1024,6 @@ public class TestFlatStyleableValue
testColor( c, ui, "error.focusedBorderColor", 0x123456 ); testColor( c, ui, "error.focusedBorderColor", 0x123456 );
testColor( c, ui, "warning.borderColor", 0x123456 ); testColor( c, ui, "warning.borderColor", 0x123456 );
testColor( c, ui, "warning.focusedBorderColor", 0x123456 ); testColor( c, ui, "warning.focusedBorderColor", 0x123456 );
testColor( c, ui, "success.borderColor", 0x123456 );
testColor( c, ui, "success.focusedBorderColor", 0x123456 );
testColor( c, ui, "custom.borderColor", 0x123456 ); testColor( c, ui, "custom.borderColor", 0x123456 );
testString( c, ui, "outline", "error" ); testString( c, ui, "outline", "error" );
@@ -1123,8 +1121,6 @@ public class TestFlatStyleableValue
testValue( border, "error.focusedBorderColor", Color.WHITE ); testValue( border, "error.focusedBorderColor", Color.WHITE );
testValue( border, "warning.borderColor", Color.WHITE ); testValue( border, "warning.borderColor", Color.WHITE );
testValue( border, "warning.focusedBorderColor", Color.WHITE ); testValue( border, "warning.focusedBorderColor", Color.WHITE );
testValue( border, "success.borderColor", Color.WHITE );
testValue( border, "success.focusedBorderColor", Color.WHITE );
testValue( border, "custom.borderColor", Color.WHITE ); testValue( border, "custom.borderColor", Color.WHITE );
} }

View File

@@ -1278,8 +1278,6 @@ public class TestFlatStyling
applyStyle.accept( "error.focusedBorderColor: #fff" ); applyStyle.accept( "error.focusedBorderColor: #fff" );
applyStyle.accept( "warning.borderColor: #fff" ); applyStyle.accept( "warning.borderColor: #fff" );
applyStyle.accept( "warning.focusedBorderColor: #fff" ); applyStyle.accept( "warning.focusedBorderColor: #fff" );
applyStyle.accept( "success.borderColor: #fff" );
applyStyle.accept( "success.focusedBorderColor: #fff" );
applyStyle.accept( "custom.borderColor: desaturate(#f00,50%,relative derived noAutoInverse)" ); applyStyle.accept( "custom.borderColor: desaturate(#f00,50%,relative derived noAutoInverse)" );
applyStyle.accept( "outline: error" ); applyStyle.accept( "outline: error" );
@@ -1365,8 +1363,6 @@ public class TestFlatStyling
border.applyStyleProperty( "error.focusedBorderColor", Color.WHITE ); border.applyStyleProperty( "error.focusedBorderColor", Color.WHITE );
border.applyStyleProperty( "warning.borderColor", Color.WHITE ); border.applyStyleProperty( "warning.borderColor", Color.WHITE );
border.applyStyleProperty( "warning.focusedBorderColor", Color.WHITE ); border.applyStyleProperty( "warning.focusedBorderColor", Color.WHITE );
border.applyStyleProperty( "success.borderColor", Color.WHITE );
border.applyStyleProperty( "success.focusedBorderColor", Color.WHITE );
border.applyStyleProperty( "custom.borderColor", Color.WHITE ); border.applyStyleProperty( "custom.borderColor", Color.WHITE );
} }

View File

@@ -1,7 +1,4 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

View File

@@ -48,9 +48,6 @@ tasks {
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) if( JavaVersion.current() >= JavaVersion.VERSION_1_9 )
attributes( "Multi-Release" to "true" ) attributes( "Multi-Release" to "true" )
// allow loading FlatLaf native library in Java 24+ (see https://openjdk.org/jeps/472)
attributes( "Enable-Native-Access" to "ALL-UNNAMED" )
} }
exclude( "module-info.class" ) exclude( "module-info.class" )

View File

@@ -179,10 +179,14 @@ class BasicComponentsPanel
JScrollPane scrollPane12 = new JScrollPane(); JScrollPane scrollPane12 = new JScrollPane();
JTextPane textPane4 = new JTextPane(); JTextPane textPane4 = new JTextPane();
JTextPane textPane5 = new JTextPane(); JTextPane textPane5 = new JTextPane();
JLabel hintsLabel = new JLabel(); JLabel errorHintsLabel = new JLabel();
JTextField errorHintsTextField = new JTextField(); JTextField errorHintsTextField = new JTextField();
JComboBox<String> errorHintsComboBox = new JComboBox<>();
JSpinner errorHintsSpinner = new JSpinner();
JLabel warningHintsLabel = new JLabel();
JTextField warningHintsTextField = new JTextField(); JTextField warningHintsTextField = new JTextField();
JTextField successHintsTextField = new JTextField(); JComboBox<String> warningHintsComboBox = new JComboBox<>();
JSpinner warningHintsSpinner = new JSpinner();
JLabel iconsLabel = new JLabel(); JLabel iconsLabel = new JLabel();
leadingIconTextField = new JTextField(); leadingIconTextField = new JTextField();
trailingIconTextField = new JTextField(); trailingIconTextField = new JTextField();
@@ -237,6 +241,7 @@ class BasicComponentsPanel
"[]" + "[]" +
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]0" + "[]0" +
"[]")); "[]"));
@@ -693,122 +698,145 @@ class BasicComponentsPanel
textPane5.setText("No scroll pane"); textPane5.setText("No scroll pane");
add(textPane5, "cell 5 11,growx"); add(textPane5, "cell 5 11,growx");
//---- hintsLabel ---- //---- errorHintsLabel ----
hintsLabel.setText("Error/warning/success:"); errorHintsLabel.setText("Error hints:");
add(hintsLabel, "cell 0 12"); add(errorHintsLabel, "cell 0 12");
//---- errorHintsTextField ---- //---- errorHintsTextField ----
errorHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR); errorHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
add(errorHintsTextField, "cell 1 12,growx"); add(errorHintsTextField, "cell 1 12,growx");
//---- errorHintsComboBox ----
errorHintsComboBox.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
errorHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"Editable"
}));
errorHintsComboBox.setEditable(true);
add(errorHintsComboBox, "cell 2 12,growx");
//---- errorHintsSpinner ----
errorHintsSpinner.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_ERROR);
add(errorHintsSpinner, "cell 3 12,growx");
//---- warningHintsLabel ----
warningHintsLabel.setText("Warning hints:");
add(warningHintsLabel, "cell 0 13");
//---- warningHintsTextField ---- //---- warningHintsTextField ----
warningHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING); warningHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
add(warningHintsTextField, "cell 2 12,growx"); add(warningHintsTextField, "cell 1 13,growx");
//---- successHintsTextField ---- //---- warningHintsComboBox ----
successHintsTextField.putClientProperty(FlatClientProperties.OUTLINE, "success"); warningHintsComboBox.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
add(successHintsTextField, "cell 3 12,growx"); warningHintsComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"Not editable"
}));
add(warningHintsComboBox, "cell 2 13,growx");
//---- warningHintsSpinner ----
warningHintsSpinner.putClientProperty(FlatClientProperties.OUTLINE, FlatClientProperties.OUTLINE_WARNING);
add(warningHintsSpinner, "cell 3 13,growx");
//---- iconsLabel ---- //---- iconsLabel ----
iconsLabel.setText("Leading/trailing icons:"); iconsLabel.setText("Leading/trailing icons:");
add(iconsLabel, "cell 0 13"); add(iconsLabel, "cell 0 14");
add(leadingIconTextField, "cell 1 13,growx"); add(leadingIconTextField, "cell 1 14,growx");
//---- trailingIconTextField ---- //---- trailingIconTextField ----
trailingIconTextField.setText("text"); trailingIconTextField.setText("text");
add(trailingIconTextField, "cell 2 13,growx"); add(trailingIconTextField, "cell 2 14,growx");
//---- iconsTextField ---- //---- iconsTextField ----
iconsTextField.setText("text"); iconsTextField.setText("text");
add(iconsTextField, "cell 3 13,growx"); add(iconsTextField, "cell 3 14,growx");
//---- compsLabel ---- //---- compsLabel ----
compsLabel.setText("Leading/trailing comp.:"); compsLabel.setText("Leading/trailing comp.:");
add(compsLabel, "cell 0 14"); add(compsLabel, "cell 0 15");
add(compsTextField, "cell 1 14 2 1,growx"); add(compsTextField, "cell 1 15 2 1,growx");
//---- clearTextField ---- //---- clearTextField ----
clearTextField.setText("clear me"); clearTextField.setText("clear me");
add(clearTextField, "cell 3 14,growx"); add(clearTextField, "cell 3 15,growx");
//---- fontsLabel ---- //---- fontsLabel ----
fontsLabel.setText("Typography / Fonts:"); fontsLabel.setText("Typography / Fonts:");
add(fontsLabel, "cell 0 15"); add(fontsLabel, "cell 0 16");
//---- h00Label ---- //---- h00Label ----
h00Label.setText("H00"); h00Label.setText("H00");
h00Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h00"); h00Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h00");
add(h00Label, "cell 1 15 5 1"); add(h00Label, "cell 1 16 5 1");
//---- h0Label ---- //---- h0Label ----
h0Label.setText("H0"); h0Label.setText("H0");
h0Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h0"); h0Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h0");
add(h0Label, "cell 1 15 5 1"); add(h0Label, "cell 1 16 5 1");
//---- h1Label ---- //---- h1Label ----
h1Label.setText("H1"); h1Label.setText("H1");
h1Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1"); h1Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h1");
add(h1Label, "cell 1 15 5 1"); add(h1Label, "cell 1 16 5 1");
//---- h2Label ---- //---- h2Label ----
h2Label.setText("H2"); h2Label.setText("H2");
h2Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h2"); h2Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h2");
add(h2Label, "cell 1 15 5 1"); add(h2Label, "cell 1 16 5 1");
//---- h3Label ---- //---- h3Label ----
h3Label.setText("H3"); h3Label.setText("H3");
h3Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3"); h3Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h3");
add(h3Label, "cell 1 15 5 1"); add(h3Label, "cell 1 16 5 1");
//---- h4Label ---- //---- h4Label ----
h4Label.setText("H4"); h4Label.setText("H4");
h4Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h4"); h4Label.putClientProperty(FlatClientProperties.STYLE_CLASS, "h4");
add(h4Label, "cell 1 15 5 1"); add(h4Label, "cell 1 16 5 1");
//---- lightLabel ---- //---- lightLabel ----
lightLabel.setText("light"); lightLabel.setText("light");
lightLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $light.font"); lightLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $light.font");
add(lightLabel, "cell 1 15 5 1,gapx 30"); add(lightLabel, "cell 1 16 5 1,gapx 30");
//---- semiboldLabel ---- //---- semiboldLabel ----
semiboldLabel.setText("semibold"); semiboldLabel.setText("semibold");
semiboldLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $semibold.font"); semiboldLabel.putClientProperty(FlatClientProperties.STYLE, "font: 200% $semibold.font");
add(semiboldLabel, "cell 1 15 5 1"); add(semiboldLabel, "cell 1 16 5 1");
//---- fontZoomLabel ---- //---- fontZoomLabel ----
fontZoomLabel.setText("(200%)"); fontZoomLabel.setText("(200%)");
fontZoomLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small"); fontZoomLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
fontZoomLabel.setEnabled(false); fontZoomLabel.setEnabled(false);
add(fontZoomLabel, "cell 1 15 5 1"); add(fontZoomLabel, "cell 1 16 5 1");
//---- largeLabel ---- //---- largeLabel ----
largeLabel.setText("large"); largeLabel.setText("large");
largeLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "large"); largeLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "large");
add(largeLabel, "cell 1 16 5 1"); add(largeLabel, "cell 1 17 5 1");
//---- defaultLabel ---- //---- defaultLabel ----
defaultLabel.setText("default"); defaultLabel.setText("default");
add(defaultLabel, "cell 1 16 5 1"); add(defaultLabel, "cell 1 17 5 1");
//---- mediumLabel ---- //---- mediumLabel ----
mediumLabel.setText("medium"); mediumLabel.setText("medium");
mediumLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "medium"); mediumLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "medium");
add(mediumLabel, "cell 1 16 5 1"); add(mediumLabel, "cell 1 17 5 1");
//---- smallLabel ---- //---- smallLabel ----
smallLabel.setText("small"); smallLabel.setText("small");
smallLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small"); smallLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "small");
add(smallLabel, "cell 1 16 5 1"); add(smallLabel, "cell 1 17 5 1");
//---- miniLabel ---- //---- miniLabel ----
miniLabel.setText("mini"); miniLabel.setText("mini");
miniLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "mini"); miniLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "mini");
add(miniLabel, "cell 1 16 5 1"); add(miniLabel, "cell 1 17 5 1");
//---- monospacedLabel ---- //---- monospacedLabel ----
monospacedLabel.setText("monospaced"); monospacedLabel.setText("monospaced");
monospacedLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "monospaced"); monospacedLabel.putClientProperty(FlatClientProperties.STYLE_CLASS, "monospaced");
add(monospacedLabel, "cell 1 16 5 1,gapx 30"); add(monospacedLabel, "cell 1 17 5 1,gapx 30");
//======== popupMenu1 ======== //======== popupMenu1 ========
{ {
@@ -847,7 +875,8 @@ class BasicComponentsPanel
editorPaneLabel, scrollPane5, scrollPane6, scrollPane7, scrollPane8, editorPane5, editorPaneLabel, scrollPane5, scrollPane6, scrollPane7, scrollPane8, editorPane5,
textPaneLabel, scrollPane9, scrollPane10, scrollPane11, scrollPane12, textPane5, textPaneLabel, scrollPane9, scrollPane10, scrollPane11, scrollPane12, textPane5,
hintsLabel, errorHintsTextField, warningHintsTextField, successHintsTextField, errorHintsLabel, errorHintsTextField, errorHintsComboBox, errorHintsSpinner,
warningHintsLabel, warningHintsTextField, warningHintsComboBox, warningHintsSpinner,
fontZoomLabel, fontZoomLabel,
}; };
@@ -870,7 +899,8 @@ class BasicComponentsPanel
rows[11].setGapBefore( zeroGap ); rows[11].setGapBefore( zeroGap );
rows[11].setGapAfter( zeroGap ); rows[11].setGapAfter( zeroGap );
rows[12].setGapBefore( zeroGap ); rows[12].setGapBefore( zeroGap );
rows[15].setGapBefore( zeroGap ); rows[13].setGapBefore( zeroGap );
rows[16].setGapBefore( zeroGap );
layout.setRowConstraints( ac ); layout.setRowConstraints( ac );
// move two text field into same row as spinners // move two text field into same row as spinners

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.3" encoding: "UTF-8" JFDML JFormDesigner: "7.0.5.0.404" Java: "17" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3" "$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[][sizegroup 1][sizegroup 1][sizegroup 1][][]" "$columnConstraints": "[][sizegroup 1][sizegroup 1][sizegroup 1][][]"
"$rowConstraints": "[][][][][][][][][][][][]para[][][][]0[]" "$rowConstraints": "[][][][][][][][][][][][]para[][][][][]0[]"
} ) { } ) {
name: "this" name: "this"
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
@@ -595,8 +595,8 @@ new FormModel {
"value": "cell 5 11,growx" "value": "cell 5 11,growx"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "hintsLabel" name: "errorHintsLabel"
"text": "Error/warning/success:" "text": "Error hints:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 12" "value": "cell 0 12"
} ) } )
@@ -606,23 +606,56 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 12,growx" "value": "cell 1 12,growx"
} ) } )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "errorHintsComboBox"
"$client.JComponent.outline": "error"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "Editable"
addElement( "Editable" )
}
"editable": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 12,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "errorHintsSpinner"
"$client.JComponent.outline": "error"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 12,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "warningHintsLabel"
"text": "Warning hints:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 13"
} )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "warningHintsTextField" name: "warningHintsTextField"
"$client.JComponent.outline": "warning" "$client.JComponent.outline": "warning"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 12,growx" "value": "cell 1 13,growx"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JComboBox" ) {
name: "successHintsTextField" name: "warningHintsComboBox"
"$client.JComponent.outline": "success" "$client.JComponent.outline": "warning"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "Not editable"
addElement( "Not editable" )
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 12,growx" "value": "cell 2 13,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "warningHintsSpinner"
"$client.JComponent.outline": "warning"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 13,growx"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "iconsLabel" name: "iconsLabel"
"text": "Leading/trailing icons:" "text": "Leading/trailing icons:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 13" "value": "cell 0 14"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "leadingIconTextField" name: "leadingIconTextField"
@@ -630,7 +663,7 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 13,growx" "value": "cell 1 14,growx"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "trailingIconTextField" name: "trailingIconTextField"
@@ -639,7 +672,7 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 13,growx" "value": "cell 2 14,growx"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "iconsTextField" name: "iconsTextField"
@@ -648,13 +681,13 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 13,growx" "value": "cell 3 14,growx"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "compsLabel" name: "compsLabel"
"text": "Leading/trailing comp.:" "text": "Leading/trailing comp.:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 14" "value": "cell 0 15"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "compsTextField" name: "compsTextField"
@@ -662,7 +695,7 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 14 2 1,growx" "value": "cell 1 15 2 1,growx"
} ) } )
add( new FormComponent( "javax.swing.JTextField" ) { add( new FormComponent( "javax.swing.JTextField" ) {
name: "clearTextField" name: "clearTextField"
@@ -671,69 +704,69 @@ new FormModel {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 14,growx" "value": "cell 3 15,growx"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fontsLabel" name: "fontsLabel"
"text": "Typography / Fonts:" "text": "Typography / Fonts:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 15" "value": "cell 0 16"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h00Label" name: "h00Label"
"text": "H00" "text": "H00"
"$client.FlatLaf.styleClass": "h00" "$client.FlatLaf.styleClass": "h00"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h0Label" name: "h0Label"
"text": "H0" "text": "H0"
"$client.FlatLaf.styleClass": "h0" "$client.FlatLaf.styleClass": "h0"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h1Label" name: "h1Label"
"text": "H1" "text": "H1"
"$client.FlatLaf.styleClass": "h1" "$client.FlatLaf.styleClass": "h1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h2Label" name: "h2Label"
"text": "H2" "text": "H2"
"$client.FlatLaf.styleClass": "h2" "$client.FlatLaf.styleClass": "h2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h3Label" name: "h3Label"
"text": "H3" "text": "H3"
"$client.FlatLaf.styleClass": "h3" "$client.FlatLaf.styleClass": "h3"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "h4Label" name: "h4Label"
"text": "H4" "text": "H4"
"$client.FlatLaf.styleClass": "h4" "$client.FlatLaf.styleClass": "h4"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "lightLabel" name: "lightLabel"
"text": "light" "text": "light"
"$client.FlatLaf.style": "font: 200% $light.font" "$client.FlatLaf.style": "font: 200% $light.font"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1,gapx 30" "value": "cell 1 16 5 1,gapx 30"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "semiboldLabel" name: "semiboldLabel"
"text": "semibold" "text": "semibold"
"$client.FlatLaf.style": "font: 200% $semibold.font" "$client.FlatLaf.style": "font: 200% $semibold.font"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fontZoomLabel" name: "fontZoomLabel"
@@ -741,52 +774,52 @@ new FormModel {
"$client.FlatLaf.styleClass": "small" "$client.FlatLaf.styleClass": "small"
"enabled": false "enabled": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15 5 1" "value": "cell 1 16 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "largeLabel" name: "largeLabel"
"text": "large" "text": "large"
"$client.FlatLaf.styleClass": "large" "$client.FlatLaf.styleClass": "large"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1" "value": "cell 1 17 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "defaultLabel" name: "defaultLabel"
"text": "default" "text": "default"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1" "value": "cell 1 17 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "mediumLabel" name: "mediumLabel"
"text": "medium" "text": "medium"
"$client.FlatLaf.styleClass": "medium" "$client.FlatLaf.styleClass": "medium"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1" "value": "cell 1 17 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "smallLabel" name: "smallLabel"
"text": "small" "text": "small"
"$client.FlatLaf.styleClass": "small" "$client.FlatLaf.styleClass": "small"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1" "value": "cell 1 17 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "miniLabel" name: "miniLabel"
"text": "mini" "text": "mini"
"$client.FlatLaf.styleClass": "mini" "$client.FlatLaf.styleClass": "mini"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1" "value": "cell 1 17 5 1"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "monospacedLabel" name: "monospacedLabel"
"text": "monospaced" "text": "monospaced"
"$client.FlatLaf.styleClass": "monospaced" "$client.FlatLaf.styleClass": "monospaced"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 16 5 1,gapx 30" "value": "cell 1 17 5 1,gapx 30"
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 840, 565 ) "size": new java.awt.Dimension( 920, 550 )
} ) } )
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) { add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu1" name: "popupMenu1"
@@ -806,7 +839,7 @@ new FormModel {
"mnemonic": 80 "mnemonic": 80
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 605 ) "location": new java.awt.Point( 0, 570 )
"size": new java.awt.Dimension( 91, 87 ) "size": new java.awt.Dimension( 91, 87 )
} ) } )
} }

View File

@@ -156,9 +156,6 @@ class ControlBar
// register Alt+Shift+F1, F2, ... keys to change system scale factor // register Alt+Shift+F1, F2, ... keys to change system scale factor
DemoPrefs.registerSystemScaleFactors( frame ); DemoPrefs.registerSystemScaleFactors( frame );
// register Alt+Shift+S to enable/disable interprocess Laf sync
DemoPrefs.initLafSync( frame );
// register ESC key to close frame // register ESC key to close frame
((JComponent)frame.getContentPane()).registerKeyboardAction( ((JComponent)frame.getContentPane()).registerKeyboardAction(
e -> { e -> {

View File

@@ -252,7 +252,7 @@ class DataComponentsPanel
"[]" + "[]" +
"[150,grow,sizegroup 1,fill]" + "[150,grow,sizegroup 1,fill]" +
"[150,grow,sizegroup 1,fill]" + "[150,grow,sizegroup 1,fill]" +
"[150,grow,fill]")); "[150,grow,sizegroup 1,fill]"));
//---- label1 ---- //---- label1 ----
label1.setText("Square Selection"); label1.setText("Square Selection");

View File

@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3" "$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[][150,fill][150,fill][150,fill][fill]" "$columnConstraints": "[][150,fill][150,fill][150,fill][fill]"
"$rowConstraints": "[][150,grow,sizegroup 1,fill][150,grow,sizegroup 1,fill][150,grow,fill]" "$rowConstraints": "[][150,grow,sizegroup 1,fill][150,grow,sizegroup 1,fill][150,grow,sizegroup 1,fill]"
} ) { } ) {
name: "this" name: "this"
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {

View File

@@ -228,20 +228,8 @@ class DemoFrame
private void windowDecorationsChanged() { private void windowDecorationsChanged() {
boolean windowDecorations = windowDecorationsCheckBoxMenuItem.isSelected(); boolean windowDecorations = windowDecorationsCheckBoxMenuItem.isSelected();
if( SystemInfo.isLinux ) {
// enable/disable custom window decorations
JFrame.setDefaultLookAndFeelDecorated( windowDecorations );
JDialog.setDefaultLookAndFeelDecorated( windowDecorations );
// dispose frame, update decoration and re-show frame
dispose();
setUndecorated( windowDecorations );
getRootPane().setWindowDecorationStyle( windowDecorations ? JRootPane.FRAME : JRootPane.NONE );
setVisible( true );
} else {
// change window decoration of all frames and dialogs // change window decoration of all frames and dialogs
FlatLaf.setUseNativeWindowDecorations( windowDecorations ); FlatLaf.setUseNativeWindowDecorations( windowDecorations );
}
menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations ); menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations );
unifiedTitleBarMenuItem.setEnabled( windowDecorations ); unifiedTitleBarMenuItem.setEnabled( windowDecorations );
@@ -498,7 +486,7 @@ class DemoFrame
} }
private boolean supportsFlatLafWindowDecorations() { private boolean supportsFlatLafWindowDecorations() {
return FlatLaf.supportsNativeWindowDecorations() || SystemInfo.isLinux; return FlatLaf.supportsNativeWindowDecorations() || (SystemInfo.isLinux && JFrame.isDefaultLookAndFeelDecorated());
} }
private void initComponents() { private void initComponents() {
@@ -991,9 +979,10 @@ class DemoFrame
scrollingPopupMenu.add( "Item " + i ); scrollingPopupMenu.add( "Item " + i );
if( supportsFlatLafWindowDecorations() ) { if( supportsFlatLafWindowDecorations() ) {
windowDecorationsCheckBoxMenuItem.setSelected( SystemInfo.isLinux if( SystemInfo.isLinux )
? JFrame.isDefaultLookAndFeelDecorated() unsupported( windowDecorationsCheckBoxMenuItem );
: FlatLaf.isUseNativeWindowDecorations() ); else
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) ); menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) ); unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) ); showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
@@ -1037,7 +1026,7 @@ class DemoFrame
private void unsupported( JCheckBoxMenuItem menuItem ) { private void unsupported( JCheckBoxMenuItem menuItem ) {
menuItem.setEnabled( false ); menuItem.setEnabled( false );
menuItem.setSelected( false ); menuItem.setSelected( false );
menuItem.setToolTipText( "Not supported on this platform." ); menuItem.setToolTipText( "Not supported on your system." );
} }
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables

View File

@@ -16,15 +16,8 @@
package com.formdev.flatlaf.demo; package com.formdev.flatlaf.demo;
import java.awt.EventQueue;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JFrame; import javax.swing.JFrame;
@@ -35,6 +28,7 @@ import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf; import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.FlatPropertiesLaf; import com.formdev.flatlaf.FlatPropertiesLaf;
import com.formdev.flatlaf.IntelliJTheme; import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
@@ -44,10 +38,14 @@ import com.formdev.flatlaf.util.SystemInfo;
*/ */
public class DemoPrefs public class DemoPrefs
{ {
public static final String KEY_LAF_CLASS_NAME = "lafClassName"; public static final String KEY_LAF = "laf";
public static final String KEY_LAF_THEME_FILE = "lafThemeFile"; public static final String KEY_LAF_THEME = "lafTheme";
public static final String KEY_SYSTEM_SCALE_FACTOR = "systemScaleFactor"; public static final String KEY_SYSTEM_SCALE_FACTOR = "systemScaleFactor";
public static final String KEY_LAF_SYNC = "lafSync";
public static final String RESOURCE_PREFIX = "res:";
public static final String FILE_PREFIX = "file:";
public static final String THEME_UI_KEY = "__FlatLaf.demo.theme";
private static Preferences state; private static Preferences state;
@@ -60,14 +58,37 @@ public class DemoPrefs
} }
public static void setupLaf( String[] args ) { public static void setupLaf( String[] args ) {
// com.formdev.flatlaf.demo.intellijthemes.IJThemesDump.install();
// set look and feel // set look and feel
try { try {
if( args.length > 0 ) if( args.length > 0 )
UIManager.setLookAndFeel( args[0] ); UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = state.get( KEY_LAF, FlatLightLaf.class.getName() );
if( IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) {
String theme = state.get( KEY_LAF_THEME, "" );
if( theme.startsWith( RESOURCE_PREFIX ) )
IntelliJTheme.setup( IJThemesPanel.class.getResourceAsStream( IJThemesPanel.THEMES_PACKAGE + theme.substring( RESOURCE_PREFIX.length() ) ) );
else if( theme.startsWith( FILE_PREFIX ) )
FlatLaf.setup( IntelliJTheme.createLaf( new FileInputStream( theme.substring( FILE_PREFIX.length() ) ) ) );
else else
restoreLaf(); FlatLightLaf.setup();
if( !theme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
} else if( FlatPropertiesLaf.class.getName().equals( lafClassName ) ) {
String theme = state.get( KEY_LAF_THEME, "" );
if( theme.startsWith( FILE_PREFIX ) ) {
File themeFile = new File( theme.substring( FILE_PREFIX.length() ) );
String themeName = StringUtils.removeTrailing( themeFile.getName(), ".properties" );
FlatLaf.setup( new FlatPropertiesLaf( themeName, themeFile ) );
} else
FlatLightLaf.setup();
if( !theme.isEmpty() )
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
} else
UIManager.setLookAndFeel( lafClassName );
}
} catch( Throwable ex ) { } catch( Throwable ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex ); LoggingFacade.INSTANCE.logSevere( null, ex );
@@ -77,44 +98,16 @@ public class DemoPrefs
// remember active look and feel // remember active look and feel
UIManager.addPropertyChangeListener( e -> { UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) { if( "lookAndFeel".equals( e.getPropertyName() ) )
state.put( KEY_LAF_CLASS_NAME, UIManager.getLookAndFeel().getClass().getName() ); state.put( KEY_LAF, UIManager.getLookAndFeel().getClass().getName() );
notifyLafChange();
}
} ); } );
} }
private static void restoreLaf()
throws Exception
{
String lafClassName = state.get( KEY_LAF_CLASS_NAME, FlatLightLaf.class.getName() );
if( FlatPropertiesLaf.class.getName().equals( lafClassName ) ||
IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) )
{
String themeFileName = state.get( KEY_LAF_THEME_FILE, "" );
if( !themeFileName.isEmpty() ) {
File themeFile = new File( themeFileName );
if( themeFileName.endsWith( ".properties" ) ) {
String themeName = StringUtils.removeTrailing( themeFile.getName(), ".properties" );
FlatLaf.setup( new FlatPropertiesLaf( themeName, themeFile ) );
} else
FlatLaf.setup( IntelliJTheme.createLaf( new FileInputStream( themeFile ) ) );
} else
FlatLightLaf.setup();
} else
UIManager.setLookAndFeel( lafClassName );
}
public static void initSystemScale() { public static void initSystemScale() {
if( System.getProperty( "sun.java2d.uiScale" ) == null ) { if( System.getProperty( "sun.java2d.uiScale" ) == null ) {
String scaleFactor = state.get( KEY_SYSTEM_SCALE_FACTOR, null ); String scaleFactor = getState().get( KEY_SYSTEM_SCALE_FACTOR, null );
if( scaleFactor != null ) { if( scaleFactor != null )
System.setProperty( "sun.java2d.uiScale", scaleFactor ); System.setProperty( "sun.java2d.uiScale", scaleFactor );
System.out.println( "FlatLaf: setting 'sun.java2d.uiScale' to " + scaleFactor );
System.out.println( " use 'Alt+Shift+F1...12' to change it to 1x...4x" );
}
} }
} }
@@ -165,113 +158,10 @@ public class DemoPrefs
return; return;
if( scaleFactor != null ) if( scaleFactor != null )
state.put( KEY_SYSTEM_SCALE_FACTOR, scaleFactor ); DemoPrefs.getState().put( KEY_SYSTEM_SCALE_FACTOR, scaleFactor );
else else
state.remove( KEY_SYSTEM_SCALE_FACTOR ); DemoPrefs.getState().remove( KEY_SYSTEM_SCALE_FACTOR );
System.exit( 0 ); System.exit( 0 );
} }
//---- inter-process Laf change notification/synchronisation --------------
// used for FlatLaf development when running multiple testing apps
private static final String MULTICAST_ADDRESS = "224.63.31.41";
private static final int MULTICAST_PORT = 36584;
private static final long PROCESS_ID = System.nanoTime();
private static Thread thread;
private static boolean notifyEnabled = true;
public static void initLafSync( JFrame frame ) {
((JComponent)frame.getContentPane()).registerKeyboardAction(
e -> enableDisableLafSync(),
KeyStroke.getKeyStroke( "alt shift S" ),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
if( state.getBoolean( KEY_LAF_SYNC, false ) ) {
System.out.println( "FlatLaf: theme sync enabled; use Alt+Shift+S to disable it" );
listenToLafChange();
}
}
private static void enableDisableLafSync() {
boolean enabled = !state.getBoolean( KEY_LAF_SYNC, false );
state.putBoolean( KEY_LAF_SYNC, enabled );
if( enabled )
listenToLafChange();
else if( thread != null) {
thread.interrupt();
thread = null;
}
}
private static void listenToLafChange() {
if( thread != null )
return;
thread = new Thread( "FlatLaf Laf change listener" ) {
MulticastSocket socket;
@Override
public void run() {
try( MulticastSocket socket = new MulticastSocket( MULTICAST_PORT ) ) {
this.socket = socket;
socket.joinGroup( InetAddress.getByName( MULTICAST_ADDRESS ) );
byte[] buffer = new byte[Long.BYTES];
for(;;) {
DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
socket.receive( packet );
long id = ByteBuffer.wrap( buffer ).getLong();
if( id == PROCESS_ID )
continue; // was sent from this process
EventQueue.invokeLater( () -> {
notifyEnabled = false;
try {
restoreLaf();
FlatLaf.updateUI();
} catch( Throwable ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
} finally {
notifyEnabled = true;
}
} );
}
} catch( IOException ex ) {
if( ex instanceof SocketException && "Socket closed".equals( ex.getMessage() ) )
return; // interrupted
LoggingFacade.INSTANCE.logSevere( null, ex );
}
}
@Override
public void interrupt() {
super.interrupt();
socket.close();
}
};
thread.setDaemon( true );
thread.start();
}
private static void notifyLafChange() {
if( thread == null || !notifyEnabled )
return;
EventQueue.invokeLater( () -> {
try( MulticastSocket socket = new MulticastSocket() ) {
InetAddress address = InetAddress.getByName( MULTICAST_ADDRESS );
byte[] buffer = ByteBuffer.wrap( new byte[Long.BYTES] ).putLong( PROCESS_ID ).array();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, address, MULTICAST_PORT );
socket.send( packet );
} catch( IOException ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
} );
}
} }

View File

@@ -25,32 +25,24 @@ class IJThemeInfo
{ {
final String name; final String name;
final String resourceName; final String resourceName;
final boolean discontinued;
final boolean dark; final boolean dark;
final String license; final String license;
final String licenseFile; final String licenseFile;
final String pluginUrl;
final String sourceCodeUrl; final String sourceCodeUrl;
final String sourceCodePath; final String sourceCodePath;
final File themeFile; final File themeFile;
final String lafClassName; final String lafClassName;
IJThemeInfo( String name, boolean dark, String lafClassName ) { IJThemeInfo( String name, String resourceName, boolean dark,
this( name, null, false, dark, null, null, null, null, null, null, lafClassName );
}
IJThemeInfo( String name, String resourceName, boolean discontinued, boolean dark,
String license, String licenseFile, String license, String licenseFile,
String pluginUrl, String sourceCodeUrl, String sourceCodePath, String sourceCodeUrl, String sourceCodePath,
File themeFile, String lafClassName ) File themeFile, String lafClassName )
{ {
this.name = name; this.name = name;
this.resourceName = resourceName; this.resourceName = resourceName;
this.discontinued = discontinued;
this.dark = dark; this.dark = dark;
this.license = license; this.license = license;
this.licenseFile = licenseFile; this.licenseFile = licenseFile;
this.pluginUrl = pluginUrl;
this.sourceCodeUrl = sourceCodeUrl; this.sourceCodeUrl = sourceCodeUrl;
this.sourceCodePath = sourceCodePath; this.sourceCodePath = sourceCodePath;
this.themeFile = themeFile; this.themeFile = themeFile;

View File

@@ -73,12 +73,10 @@ public class IJThemesClassGenerator
name = name.substring( nameSep + 1 ).trim(); name = name.substring( nameSep + 1 ).trim();
String themeName = name; String themeName = name;
StringBuilder buf = new StringBuilder(); if( "material-theme-ui-lite".equals( resourcePath ) )
if( "material-theme-ui-lite".equals( resourcePath ) ) {
themeName += " (Material)"; themeName += " (Material)";
buf.append( "MT" );
}
StringBuilder buf = new StringBuilder();
for( String n : name.split( "[ \\-]" ) ) { for( String n : name.split( "[ \\-]" ) ) {
if( n.length() == 0 || n.equals( "-" ) ) if( n.length() == 0 || n.equals( "-" ) )
continue; continue;

View File

@@ -1,118 +0,0 @@
/*
* Copyright 2025 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.demo.intellijthemes;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.util.LoggingFacade;
/**
* @author Karl Tauber
*/
public class IJThemesDump
{
// same as UIDefaultsLoader.KEY_PROPERTIES
private static final String KEY_PROPERTIES = "FlatLaf.internal.properties";
public static void enablePropertiesRecording() {
System.setProperty( KEY_PROPERTIES, "true" );
}
public static void install() {
enablePropertiesRecording();
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
if( lookAndFeel instanceof IntelliJTheme.ThemeLaf ) {
IntelliJTheme theme = (lookAndFeel.getClass() == IntelliJTheme.ThemeLaf.class)
? ((IntelliJTheme.ThemeLaf)lookAndFeel).getTheme()
: null;
String name = (theme != null) ? theme.name : lookAndFeel.getClass().getSimpleName();
File dir = new File( "dumps/properties" );
dumpProperties( dir, name, UIManager.getLookAndFeelDefaults() );
}
}
} );
}
public static void dumpProperties( File dir, String name, UIDefaults defaults ) {
String content = dumpPropertiesToString( defaults );
if( content == null )
return;
// write to file
File file = new File( dir, name + ".properties" );
file.getParentFile().mkdirs();
try( Writer fileWriter = new OutputStreamWriter(
new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
{
fileWriter.write( content );
} catch( IOException ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
}
public static String dumpPropertiesToString( UIDefaults defaults ) {
Properties properties = (Properties) defaults.get( KEY_PROPERTIES );
if( properties == null )
return null;
// dump to string
StringWriter stringWriter = new StringWriter( 100000 );
PrintWriter out = new PrintWriter( stringWriter );
out.printf( "@baseTheme = %s%n", FlatLaf.isLafDark() ? "dark" : "light" );
AtomicReference<String> lastPrefix = new AtomicReference<>();
properties.entrySet().stream()
.sorted( (e1, e2) -> ((String)e1.getKey()).compareTo( (String) e2.getKey() ) )
.forEach( e -> {
String key = (String) e.getKey();
String value = (String) e.getValue();
String prefix = keyPrefix( key );
if( !prefix.equals( lastPrefix.get() ) ) {
lastPrefix.set( prefix );
out.printf( "%n%n#---- %s ----%n%n", prefix );
}
out.printf( "%-50s = %s%n", key, value.replace( ";", "; \\\n\t" ) );
} );
return stringWriter.toString().replace( "\r", "" );
}
private static String keyPrefix( String key ) {
int dotIndex = key.indexOf( '.' );
return (dotIndex > 0)
? key.substring( 0, dotIndex )
: key.endsWith( "UI" )
? key.substring( 0, key.length() - 2 )
: "";
}
}

View File

@@ -56,17 +56,13 @@ class IJThemesManager
String resourceName = e.getKey(); String resourceName = e.getKey();
Map<String, String> value = (Map<String, String>) e.getValue(); Map<String, String> value = (Map<String, String>) e.getValue();
String name = value.get( "name" ); String name = value.get( "name" );
boolean discontinued = Boolean.parseBoolean( value.get( "discontinued" ) );
boolean dark = Boolean.parseBoolean( value.get( "dark" ) ); boolean dark = Boolean.parseBoolean( value.get( "dark" ) );
String lafClassName = value.get( "lafClassName" );
String license = value.get( "license" ); String license = value.get( "license" );
String licenseFile = value.get( "licenseFile" ); String licenseFile = value.get( "licenseFile" );
String pluginUrl = value.get( "pluginUrl" );
String sourceCodeUrl = value.get( "sourceCodeUrl" ); String sourceCodeUrl = value.get( "sourceCodeUrl" );
String sourceCodePath = value.get( "sourceCodePath" ); String sourceCodePath = value.get( "sourceCodePath" );
bundledThemes.add( new IJThemeInfo( name, resourceName, discontinued, dark, bundledThemes.add( new IJThemeInfo( name, resourceName, dark, license, licenseFile, sourceCodeUrl, sourceCodePath, null, null ) );
license, licenseFile, pluginUrl, sourceCodeUrl, sourceCodePath, null, lafClassName ) );
} }
} }
@@ -89,7 +85,7 @@ class IJThemesManager
String name = fname.endsWith( ".properties" ) String name = fname.endsWith( ".properties" )
? StringUtils.removeTrailing( fname, ".properties" ) ? StringUtils.removeTrailing( fname, ".properties" )
: StringUtils.removeTrailing( fname, ".theme.json" ); : StringUtils.removeTrailing( fname, ".theme.json" );
moreThemes.add( new IJThemeInfo( name, null, false, false, null, null, null, null, null, f, null ) ); moreThemes.add( new IJThemeInfo( name, null, false, null, null, null, null, f, null ) );
lastModifiedMap.put( f, f.lastModified() ); lastModifiedMap.put( f, f.lastModified() );
} }
} }

View File

@@ -33,6 +33,8 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
@@ -57,6 +59,7 @@ import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.themes.*; import com.formdev.flatlaf.themes.*;
import com.formdev.flatlaf.ui.FlatListUI; import com.formdev.flatlaf.ui.FlatListUI;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.StringUtils;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -79,13 +82,14 @@ public class IJThemesPanel
}; };
private Window window; private Window window;
private File lastDirectory;
private boolean isAdjustingThemesList; private boolean isAdjustingThemesList;
private long lastLafChangeTime = System.currentTimeMillis(); private long lastLafChangeTime = System.currentTimeMillis();
public IJThemesPanel() { public IJThemesPanel() {
initComponents(); initComponents();
pluginButton.setEnabled( false ); saveButton.setEnabled( false );
sourceCodeButton.setEnabled( false ); sourceCodeButton.setEnabled( false );
// create renderer // create renderer
@@ -140,7 +144,7 @@ public class IJThemesPanel
private String buildToolTip( IJThemeInfo ti ) { private String buildToolTip( IJThemeInfo ti ) {
if( ti.themeFile != null ) if( ti.themeFile != null )
return ti.themeFile.getPath(); return ti.themeFile.getPath();
if( ti.license == null ) if( ti.resourceName == null )
return ti.name; return ti.name;
return "Name: " + ti.name return "Name: " + ti.name
@@ -175,18 +179,18 @@ public class IJThemesPanel
// add core themes at beginning // add core themes at beginning
categories.put( themes.size(), "Core Themes" ); categories.put( themes.size(), "Core Themes" );
if( showLight ) if( showLight )
themes.add( new IJThemeInfo( "FlatLaf Light", false, FlatLightLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf Light", null, false, null, null, null, null, null, FlatLightLaf.class.getName() ) );
if( showDark ) if( showDark )
themes.add( new IJThemeInfo( "FlatLaf Dark", true, FlatDarkLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf Dark", null, true, null, null, null, null, null, FlatDarkLaf.class.getName() ) );
if( showLight ) if( showLight )
themes.add( new IJThemeInfo( "FlatLaf IntelliJ", false, FlatIntelliJLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf IntelliJ", null, false, null, null, null, null, null, FlatIntelliJLaf.class.getName() ) );
if( showDark ) if( showDark )
themes.add( new IJThemeInfo( "FlatLaf Darcula", true, FlatDarculaLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf Darcula", null, true, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
if( showLight ) if( showLight )
themes.add( new IJThemeInfo( "FlatLaf macOS Light", false, FlatMacLightLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf macOS Light", null, false, null, null, null, null, null, FlatMacLightLaf.class.getName() ) );
if( showDark ) if( showDark )
themes.add( new IJThemeInfo( "FlatLaf macOS Dark", true, FlatMacDarkLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf macOS Dark", null, true, null, null, null, null, null, FlatMacDarkLaf.class.getName() ) );
// add themes from directory // add themes from directory
categories.put( themes.size(), "Current Directory" ); categories.put( themes.size(), "Current Directory" );
@@ -234,6 +238,7 @@ public class IJThemesPanel
for( int i = 0; i < themes.size(); i++ ) { for( int i = 0; i < themes.size(); i++ ) {
IJThemeInfo theme = themes.get( i ); IJThemeInfo theme = themes.get( i );
if( oldSel.name.equals( theme.name ) && if( oldSel.name.equals( theme.name ) &&
Objects.equals( oldSel.resourceName, theme.resourceName ) &&
Objects.equals( oldSel.themeFile, theme.themeFile ) && Objects.equals( oldSel.themeFile, theme.themeFile ) &&
Objects.equals( oldSel.lafClassName, theme.lafClassName ) ) Objects.equals( oldSel.lafClassName, theme.lafClassName ) )
{ {
@@ -269,27 +274,27 @@ public class IJThemesPanel
private void themesListValueChanged( ListSelectionEvent e ) { private void themesListValueChanged( ListSelectionEvent e ) {
IJThemeInfo themeInfo = themesList.getSelectedValue(); IJThemeInfo themeInfo = themesList.getSelectedValue();
pluginButton.setEnabled( themeInfo != null && themeInfo.pluginUrl != null ); boolean bundledTheme = (themeInfo != null && themeInfo.resourceName != null);
sourceCodeButton.setEnabled( themeInfo != null && themeInfo.sourceCodePath != null ); saveButton.setEnabled( bundledTheme );
sourceCodeButton.setEnabled( bundledTheme );
if( e.getValueIsAdjusting() || isAdjustingThemesList ) if( e.getValueIsAdjusting() || isAdjustingThemesList )
return; return;
EventQueue.invokeLater( () -> { EventQueue.invokeLater( () -> {
setTheme( themeInfo, false ); setTheme( themeInfo );
} ); } );
} }
private void setTheme( IJThemeInfo themeInfo, boolean reload ) { private void setTheme( IJThemeInfo themeInfo ) {
if( themeInfo == null ) if( themeInfo == null )
return; return;
// change look and feel // change look and feel
if( themeInfo.lafClassName != null ) { if( themeInfo.lafClassName != null ) {
if( !reload && themeInfo.lafClassName.equals( UIManager.getLookAndFeel().getClass().getName() ) ) if( themeInfo.lafClassName.equals( UIManager.getLookAndFeel().getClass().getName() ) )
return; return;
if( !reload )
FlatAnimatedLafChange.showSnapshot(); FlatAnimatedLafChange.showSnapshot();
try { try {
@@ -299,59 +304,81 @@ public class IJThemesPanel
showInformationDialog( "Failed to create '" + themeInfo.lafClassName + "'.", ex ); showInformationDialog( "Failed to create '" + themeInfo.lafClassName + "'.", ex );
} }
} else if( themeInfo.themeFile != null ) { } else if( themeInfo.themeFile != null ) {
if( !reload )
FlatAnimatedLafChange.showSnapshot(); FlatAnimatedLafChange.showSnapshot();
try { try {
if( themeInfo.themeFile.getName().endsWith( ".properties" ) ) if( themeInfo.themeFile.getName().endsWith( ".properties" ) ) {
FlatLaf.setup( new FlatPropertiesLaf( themeInfo.name, themeInfo.themeFile ) ); FlatLaf.setup( new FlatPropertiesLaf( themeInfo.name, themeInfo.themeFile ) );
else } else
FlatLaf.setup( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) ); FlatLaf.setup( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) );
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME_FILE, themeInfo.themeFile.getAbsolutePath() ); DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.FILE_PREFIX + themeInfo.themeFile );
} catch( Exception ex ) { } catch( Exception ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex ); LoggingFacade.INSTANCE.logSevere( null, ex );
showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex ); showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex );
} }
} else { } else {
JOptionPane.showMessageDialog( SwingUtilities.windowForComponent( this ), FlatAnimatedLafChange.showSnapshot();
"Missing lafClassName for '" + themeInfo.name + "'",
"FlatLaf", JOptionPane.INFORMATION_MESSAGE ); IntelliJTheme.setup( getClass().getResourceAsStream( THEMES_PACKAGE + themeInfo.resourceName ) );
return; DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.RESOURCE_PREFIX + themeInfo.resourceName );
} }
// update all components // update all components
FlatLaf.updateUI(); FlatLaf.updateUI();
if( !reload )
FlatAnimatedLafChange.hideSnapshotWithAnimation(); FlatAnimatedLafChange.hideSnapshotWithAnimation();
} }
private void browsePlugin() { private void saveTheme() {
IJThemeInfo themeInfo = themesList.getSelectedValue(); IJThemeInfo themeInfo = themesList.getSelectedValue();
if( themeInfo == null || themeInfo.pluginUrl == null ) if( themeInfo == null || themeInfo.resourceName == null )
return; return;
browse( themeInfo.pluginUrl ); JFileChooser fileChooser = new JFileChooser();
fileChooser.setSelectedFile( new File( lastDirectory, themeInfo.resourceName ) );
if( fileChooser.showSaveDialog( SwingUtilities.windowForComponent( this ) ) != JFileChooser.APPROVE_OPTION )
return;
File file = fileChooser.getSelectedFile();
lastDirectory = file.getParentFile();
// save theme
try {
Files.copy( getClass().getResourceAsStream( THEMES_PACKAGE + themeInfo.resourceName ),
file.toPath(), StandardCopyOption.REPLACE_EXISTING );
} catch( IOException ex ) {
showInformationDialog( "Failed to save theme to '" + file + "'.", ex );
return;
}
// save license
if( themeInfo.licenseFile != null ) {
try {
File licenseFile = new File( file.getParentFile(),
StringUtils.removeTrailing( file.getName(), ".theme.json" ) +
themeInfo.licenseFile.substring( themeInfo.licenseFile.indexOf( '.' ) ) );
Files.copy( getClass().getResourceAsStream( THEMES_PACKAGE + themeInfo.licenseFile ),
licenseFile.toPath(), StandardCopyOption.REPLACE_EXISTING );
} catch( IOException ex ) {
showInformationDialog( "Failed to save theme license to '" + file + "'.", ex );
return;
}
}
} }
private void browseSourceCode() { private void browseSourceCode() {
IJThemeInfo themeInfo = themesList.getSelectedValue(); IJThemeInfo themeInfo = themesList.getSelectedValue();
if( themeInfo == null || themeInfo.sourceCodeUrl == null ) if( themeInfo == null || themeInfo.resourceName == null )
return; return;
String themeUrl = themeInfo.sourceCodeUrl; String themeUrl = themeInfo.sourceCodeUrl;
if( themeInfo.sourceCodePath != null ) if( themeInfo.sourceCodePath != null )
themeUrl += '/' + themeInfo.sourceCodePath; themeUrl += '/' + themeInfo.sourceCodePath;
browse( themeUrl ); themeUrl = themeUrl.replace( " ", "%20" );
}
private void browse( String url ) {
url = url.replace( " ", "%20" );
try { try {
Desktop.getDesktop().browse( new URI( url ) ); Desktop.getDesktop().browse( new URI( themeUrl ) );
} catch( IOException | URISyntaxException ex ) { } catch( IOException | URISyntaxException ex ) {
showInformationDialog( "Failed to browse '" + url + "'.", ex ); showInformationDialog( "Failed to browse '" + themeUrl + "'.", ex );
} }
} }
@@ -387,11 +414,8 @@ public class IJThemesPanel
private void lafChanged( PropertyChangeEvent e ) { private void lafChanged( PropertyChangeEvent e ) {
if( "lookAndFeel".equals( e.getPropertyName() ) ) { if( "lookAndFeel".equals( e.getPropertyName() ) ) {
// use invokeLater() because KEY_LAF_THEME_FILE is updated after this event
EventQueue.invokeLater( () -> {
selectedCurrentLookAndFeel(); selectedCurrentLookAndFeel();
lastLafChangeTime = System.currentTimeMillis(); lastLafChangeTime = System.currentTimeMillis();
} );
} }
} }
@@ -406,19 +430,19 @@ public class IJThemesPanel
if( laf instanceof FlatLaf ) { if( laf instanceof FlatLaf ) {
List<Class<?>> lafClasses = new ArrayList<>(); List<Class<?>> lafClasses = new ArrayList<>();
// same as in UIDefaultsLoader.getLafClassesForDefaultsLoading() if( laf instanceof IntelliJTheme.ThemeLaf ) {
boolean dark = ((FlatLaf)laf).isDark();
lafClasses.add( FlatLaf.class );
lafClasses.add( dark ? FlatDarkLaf.class : FlatLightLaf.class );
lafClasses.add( dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
lafClasses.add( IntelliJTheme.ThemeLaf.class );
} else {
for( Class<?> lafClass = laf.getClass(); for( Class<?> lafClass = laf.getClass();
FlatLaf.class.isAssignableFrom( lafClass ); FlatLaf.class.isAssignableFrom( lafClass );
lafClass = lafClass.getSuperclass() ) lafClass = lafClass.getSuperclass() )
{ {
lafClasses.add( 0, lafClass ); lafClasses.add( 0, lafClass );
} }
// same as in IntelliJTheme.ThemeLaf.getLafClassesForDefaultsLoading()
if( laf instanceof IntelliJTheme.ThemeLaf ) {
boolean dark = ((FlatLaf)laf).isDark();
lafClasses.add( 1, dark ? FlatDarkLaf.class : FlatLightLaf.class );
lafClasses.add( 2, dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
} }
boolean reload = false; boolean reload = false;
@@ -439,25 +463,29 @@ public class IJThemesPanel
} }
if( reload ) if( reload )
setTheme( themesList.getSelectedValue(), true ); setTheme( themesList.getSelectedValue() );
} }
} }
} }
private void selectedCurrentLookAndFeel() { private void selectedCurrentLookAndFeel() {
Predicate<IJThemeInfo> test; LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
String lafClassName = UIManager.getLookAndFeel().getClass().getName(); String theme = UIManager.getLookAndFeelDefaults().getString( DemoPrefs.THEME_UI_KEY );
if( FlatPropertiesLaf.class.getName().equals( lafClassName ) ||
IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) if( theme == null && (lookAndFeel instanceof IntelliJTheme.ThemeLaf || lookAndFeel instanceof FlatPropertiesLaf) )
{
String themeFileName = DemoPrefs.getState().get( DemoPrefs.KEY_LAF_THEME_FILE, "" );
if( themeFileName == null )
return; return;
File themeFile = new File( themeFileName ); Predicate<IJThemeInfo> test;
if( theme != null && theme.startsWith( DemoPrefs.RESOURCE_PREFIX ) ) {
String resourceName = theme.substring( DemoPrefs.RESOURCE_PREFIX.length() );
test = ti -> Objects.equals( ti.resourceName, resourceName );
} else if( theme != null && theme.startsWith( DemoPrefs.FILE_PREFIX ) ) {
File themeFile = new File( theme.substring( DemoPrefs.FILE_PREFIX.length() ) );
test = ti -> Objects.equals( ti.themeFile, themeFile ); test = ti -> Objects.equals( ti.themeFile, themeFile );
} else } else {
String lafClassName = lookAndFeel.getClass().getName();
test = ti -> Objects.equals( ti.lafClassName, lafClassName ); test = ti -> Objects.equals( ti.lafClassName, lafClassName );
}
int newSel = -1; int newSel = -1;
for( int i = 0; i < themes.size(); i++ ) { for( int i = 0; i < themes.size(); i++ ) {
@@ -484,7 +512,7 @@ public class IJThemesPanel
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel themesLabel = new JLabel(); JLabel themesLabel = new JLabel();
toolBar = new JToolBar(); toolBar = new JToolBar();
pluginButton = new JButton(); saveButton = new JButton();
sourceCodeButton = new JButton(); sourceCodeButton = new JButton();
filterComboBox = new JComboBox<>(); filterComboBox = new JComboBox<>();
themesScrollPane = new JScrollPane(); themesScrollPane = new JScrollPane();
@@ -507,11 +535,11 @@ public class IJThemesPanel
{ {
toolBar.setFloatable(false); toolBar.setFloatable(false);
//---- pluginButton ---- //---- saveButton ----
pluginButton.setToolTipText("Opens the IntelliJ plugin page of selected IntelliJ theme in the browser."); saveButton.setToolTipText("Save .theme.json of selected IntelliJ theme to file.");
pluginButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/plugin.svg")); saveButton.setIcon(new FlatSVGIcon("com/formdev/flatlaf/demo/icons/download.svg"));
pluginButton.addActionListener(e -> browsePlugin()); saveButton.addActionListener(e -> saveTheme());
toolBar.add(pluginButton); toolBar.add(saveButton);
//---- sourceCodeButton ---- //---- sourceCodeButton ----
sourceCodeButton.setToolTipText("Opens the source code repository of selected IntelliJ theme in the browser."); sourceCodeButton.setToolTipText("Opens the source code repository of selected IntelliJ theme in the browser.");
@@ -546,7 +574,7 @@ public class IJThemesPanel
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JToolBar toolBar; private JToolBar toolBar;
private JButton pluginButton; private JButton saveButton;
private JButton sourceCodeButton; private JButton sourceCodeButton;
private JComboBox<String> filterComboBox; private JComboBox<String> filterComboBox;
private JScrollPane themesScrollPane; private JScrollPane themesScrollPane;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.3" encoding: "UTF-8" JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -22,10 +22,10 @@ new FormModel {
name: "toolBar" name: "toolBar"
"floatable": false "floatable": false
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "pluginButton" name: "saveButton"
"toolTipText": "Opens the IntelliJ plugin page of selected IntelliJ theme in the browser." "toolTipText": "Save .theme.json of selected IntelliJ theme to file."
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/plugin.svg" ) "icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/download.svg" )
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "browsePlugin", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveTheme", false ) )
} ) } )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "sourceCodeButton" name: "sourceCodeButton"

View File

@@ -38,9 +38,6 @@ public class IJThemesUpdater
themesManager.loadBundledThemes(); themesManager.loadBundledThemes();
for( IJThemeInfo ti : themesManager.bundledThemes ) { for( IJThemeInfo ti : themesManager.bundledThemes ) {
if( ti.discontinued )
continue;
if( ti.sourceCodeUrl == null || ti.sourceCodePath == null ) { if( ti.sourceCodeUrl == null || ti.sourceCodePath == null ) {
System.out.println( " " + ti.name + " NOT downloaded. Needs manual update from release on JetBrains Plugin portal." ); System.out.println( " " + ti.name + " NOT downloaded. Needs manual update from release on JetBrains Plugin portal." );
continue; continue;

View File

@@ -0,0 +1,7 @@
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-rule="evenodd">
<polygon fill="#6E6E6E" points="9 7 12 7 8 11 4 7 7 7 7 2 9 2" transform="matrix(-1 0 0 1 16 0)"/>
<rect width="12" height="2" x="2" y="12" fill="#6E6E6E"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 448 B

View File

@@ -1,4 +0,0 @@
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 4H7C5.34315 4 4 5.34315 4 7V9C4 10.6569 5.34315 12 7 12H11V11V10V6V5V4ZM12 5V4C12 3.44772 11.5523 3 11 3H7C5.13616 3 3.57006 4.27477 3.12602 6H1C0.447715 6 0 6.44772 0 7V9C0 9.55228 0.447715 10 1 10H3.12602C3.57006 11.7252 5.13616 13 7 13H11C11.5523 13 12 12.5523 12 12V11H15.5C15.7761 11 16 10.7761 16 10.5C16 10.2239 15.7761 10 15.5 10H12V6H15.5C15.7761 6 16 5.77614 16 5.5C16 5.22386 15.7761 5 15.5 5H12ZM3 7V9H1V7L3 7Z" fill="#6C707E"/>
</svg>

Before

Width:  |  Height:  |  Size: 724 B

View File

@@ -1,4 +0,0 @@
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 4H7C5.34315 4 4 5.34315 4 7V9C4 10.6569 5.34315 12 7 12H11V11V10V6V5V4ZM12 5V4C12 3.44772 11.5523 3 11 3H7C5.13616 3 3.57006 4.27477 3.12602 6H1C0.447715 6 0 6.44772 0 7V9C0 9.55228 0.447715 10 1 10H3.12602C3.57006 11.7252 5.13616 13 7 13H11C11.5523 13 12 12.5523 12 12V11H15.5C15.7761 11 16 10.7761 16 10.5C16 10.2239 15.7761 10 15.5 10H12V6H15.5C15.7761 6 16 5.77614 16 5.5C16 5.22386 15.7761 5 15.5 5H12ZM3 7V9H1V7L3 7Z" fill="#CED0D6"/>
</svg>

Before

Width:  |  Height:  |  Size: 724 B

View File

@@ -1,213 +1,186 @@
{ {
"arc-theme.theme.json": { "arc-theme.theme.json": {
"name": "Arc", "name": "Arc",
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatArcIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "arc-themes.LICENSE.txt", "licenseFile": "arc-themes.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12451-arc-theme",
"sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea", "sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea",
"sourceCodePath": "blob/master/arc-theme-idea-light/resources/arc-theme.theme.json" "sourceCodePath": "blob/master/arc-theme-idea-light/resources/arc-theme.theme.json"
}, },
"arc-theme-orange.theme.json": { "arc-theme-orange.theme.json": {
"name": "Arc - Orange", "name": "Arc - Orange",
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatArcOrangeIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "arc-themes.LICENSE.txt", "licenseFile": "arc-themes.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12451-arc-theme",
"sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea", "sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea",
"sourceCodePath": "blob/master/arc-theme-idea-light/resources/arc-theme-orange.theme.json" "sourceCodePath": "blob/master/arc-theme-idea-light/resources/arc-theme-orange.theme.json"
}, },
"arc_theme_dark.theme.json": { "arc_theme_dark.theme.json": {
"name": "Arc Dark", "name": "Arc Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatArcDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "arc-themes.LICENSE.txt", "licenseFile": "arc-themes.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/15175-arc-theme-dark",
"sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea", "sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea",
"sourceCodePath": "blob/master/arc-theme-idea-dark/resources/arc_theme_dark.theme.json" "sourceCodePath": "blob/master/arc-theme-idea-dark/resources/arc_theme_dark.theme.json"
}, },
"arc_theme_dark_orange.theme.json": { "arc_theme_dark_orange.theme.json": {
"name": "Arc Dark - Orange", "name": "Arc Dark - Orange",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatArcDarkOrangeIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "arc-themes.LICENSE.txt", "licenseFile": "arc-themes.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/15175-arc-theme-dark",
"sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea", "sourceCodeUrl": "https://gitlab.com/zlamalp/arc-theme-idea",
"sourceCodePath": "blob/master/arc-theme-idea-dark/resources/arc_theme_dark_orange.theme.json" "sourceCodePath": "blob/master/arc-theme-idea-dark/resources/arc_theme_dark_orange.theme.json"
}, },
"Carbon.theme.json": { "Carbon.theme.json": {
"name": "Carbon", "name": "Carbon",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatCarbonIJTheme",
"license": "Apache License 2.0", "license": "Apache License 2.0",
"licenseFile": "arc-themes.LICENSE.txt", "licenseFile": "arc-themes.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12280-carbon",
"sourceCodeUrl": "https://github.com/luisfer0793/theme-carbon", "sourceCodeUrl": "https://github.com/luisfer0793/theme-carbon",
"sourceCodePath": "blob/master/resources/matte_carbon_basics.theme.json" "sourceCodePath": "blob/master/resources/matte_carbon_basics.theme.json"
}, },
"Cobalt_2.theme.json": { "Cobalt_2.theme.json": {
"name": "Cobalt 2", "name": "Cobalt 2",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatCobalt2IJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Cobalt_2.LICENSE.txt", "licenseFile": "Cobalt_2.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/10745-cobalt-2",
"sourceCodeUrl": "https://github.com/ngehlert/cobalt2", "sourceCodeUrl": "https://github.com/ngehlert/cobalt2",
"sourceCodePath": "blob/master/Cobalt2-UI-Theme/resources/Cobalt_2.theme.json" "sourceCodePath": "blob/master/Cobalt2-UI-Theme/resources/Cobalt_2.theme.json"
}, },
"Cyan.theme.json": { "Cyan.theme.json": {
"name": "Cyan light", "name": "Cyan light",
"license": "MIT", "license": "MIT",
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatCyanLightIJTheme",
"licenseFile": "Cyan.LICENSE.txt", "licenseFile": "Cyan.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12102-cyan-light-theme",
"sourceCodeUrl": "https://github.com/OlyaB/CyanTheme", "sourceCodeUrl": "https://github.com/OlyaB/CyanTheme",
"sourceCodePath": "blob/master/src/Cyan.theme.json" "sourceCodePath": "blob/master/src/Cyan.theme.json"
}, },
"DarkFlatTheme.theme.json": { "DarkFlatTheme.theme.json": {
"name": "Dark Flat", "name": "Dark Flat",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatDarkFlatIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "DarkFlatTheme.LICENSE.txt", "licenseFile": "DarkFlatTheme.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12165-dark-flat-theme",
"sourceCodeUrl": "https://github.com/nerzhulart/DarkFlatTheme", "sourceCodeUrl": "https://github.com/nerzhulart/DarkFlatTheme",
"sourceCodePath": "blob/master/src/DarkFlatTheme.theme.json" "sourceCodePath": "blob/master/src/DarkFlatTheme.theme.json"
}, },
"DarkPurple.theme.json": { "DarkPurple.theme.json": {
"name": "Dark purple", "name": "Dark purple",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatDarkPurpleIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "DarkPurple.LICENSE.txt", "licenseFile": "DarkPurple.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12100-dark-purple-theme",
"sourceCodeUrl": "https://github.com/OlyaB/DarkPurpleTheme", "sourceCodeUrl": "https://github.com/OlyaB/DarkPurpleTheme",
"sourceCodePath": "blob/master/src/DarkPurple.theme.json" "sourceCodePath": "blob/master/src/DarkPurple.theme.json"
}, },
"Dracula.theme.json": { "Dracula.theme.json": {
"name": "Dracula", "name": "Dracula",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatDraculaIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Dracula.LICENSE.txt", "licenseFile": "Dracula.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12275-dracula-theme",
"sourceCodeUrl": "https://github.com/dracula/jetbrains", "sourceCodeUrl": "https://github.com/dracula/jetbrains",
"sourceCodePath": "blob/master/src/main/resources/themes/Dracula.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/Dracula.theme.json"
}, },
"Gradianto_dark_fuchsia.theme.json": { "Gradianto_dark_fuchsia.theme.json": {
"name": "Gradianto Dark Fuchsia", "name": "Gradianto Dark Fuchsia",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGradiantoDarkFuchsiaIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Gradianto.LICENSE.txt", "licenseFile": "Gradianto.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12334-gradianto",
"sourceCodeUrl": "https://github.com/thvardhan/Gradianto", "sourceCodeUrl": "https://github.com/thvardhan/Gradianto",
"sourceCodePath": "blob/master/src/main/resources/Gradianto_dark_fuchsia.theme.json" "sourceCodePath": "blob/master/src/main/resources/Gradianto_dark_fuchsia.theme.json"
}, },
"Gradianto_deep_ocean.theme.json": { "Gradianto_deep_ocean.theme.json": {
"name": "Gradianto Deep Ocean", "name": "Gradianto Deep Ocean",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGradiantoDeepOceanIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Gradianto.LICENSE.txt", "licenseFile": "Gradianto.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12334-gradianto",
"sourceCodeUrl": "https://github.com/thvardhan/Gradianto", "sourceCodeUrl": "https://github.com/thvardhan/Gradianto",
"sourceCodePath": "blob/master/src/main/resources/Gradianto_deep_ocean.theme.json" "sourceCodePath": "blob/master/src/main/resources/Gradianto_deep_ocean.theme.json"
}, },
"Gradianto_midnight_blue.theme.json": { "Gradianto_midnight_blue.theme.json": {
"name": "Gradianto Midnight Blue", "name": "Gradianto Midnight Blue",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGradiantoMidnightBlueIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Gradianto.LICENSE.txt", "licenseFile": "Gradianto.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12334-gradianto",
"sourceCodeUrl": "https://github.com/thvardhan/Gradianto", "sourceCodeUrl": "https://github.com/thvardhan/Gradianto",
"sourceCodePath": "blob/master/src/main/resources/Gradianto_midnight_blue.theme.json" "sourceCodePath": "blob/master/src/main/resources/Gradianto_midnight_blue.theme.json"
}, },
"Gradianto_Nature_Green.theme.json": { "Gradianto_Nature_Green.theme.json": {
"name": "Gradianto Nature Green", "name": "Gradianto Nature Green",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGradiantoNatureGreenIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Gradianto.LICENSE.txt", "licenseFile": "Gradianto.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12334-gradianto",
"sourceCodeUrl": "https://github.com/thvardhan/Gradianto", "sourceCodeUrl": "https://github.com/thvardhan/Gradianto",
"sourceCodePath": "blob/master/src/main/resources/Gradianto_Nature_Green.theme.json" "sourceCodePath": "blob/master/src/main/resources/Gradianto_Nature_Green.theme.json"
}, },
"Gray.theme.json": { "Gray.theme.json": {
"name": "Gray", "name": "Gray",
"license": "MIT", "license": "MIT",
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGrayIJTheme",
"licenseFile": "Gray.LICENSE.txt", "licenseFile": "Gray.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12103-gray-theme",
"sourceCodeUrl": "https://github.com/OlyaB/GreyTheme", "sourceCodeUrl": "https://github.com/OlyaB/GreyTheme",
"sourceCodePath": "blob/master/src/Gray.theme.json" "sourceCodePath": "blob/master/src/Gray.theme.json"
}, },
"gruvbox_dark_hard.theme.json": { "gruvbox_dark_hard.theme.json": {
"name": "Gruvbox Dark Hard", "name": "Gruvbox Dark Hard",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkHardIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "gruvbox_theme.LICENSE.txt", "licenseFile": "gruvbox_theme.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12310-gruvbox-theme",
"sourceCodeUrl": "https://github.com/Vincent-P/gruvbox-intellij-theme", "sourceCodeUrl": "https://github.com/Vincent-P/gruvbox-intellij-theme",
"sourceCodePath": "blob/master/src/main/resources/gruvbox_dark_hard.theme.json" "sourceCodePath": "blob/master/src/main/resources/gruvbox_dark_hard.theme.json"
}, },
"gruvbox_dark_medium.theme.json": {
"name": "Gruvbox Dark Medium",
"dark": true,
"license": "MIT",
"licenseFile": "gruvbox_theme.LICENSE.txt",
"sourceCodeUrl": "https://github.com/Vincent-P/gruvbox-intellij-theme",
"sourceCodePath": "blob/master/src/main/resources/gruvbox_dark_medium.theme.json"
},
"gruvbox_dark_soft.theme.json": {
"name": "Gruvbox Dark Soft",
"dark": true,
"license": "MIT",
"licenseFile": "gruvbox_theme.LICENSE.txt",
"sourceCodeUrl": "https://github.com/Vincent-P/gruvbox-intellij-theme",
"sourceCodePath": "blob/master/src/main/resources/gruvbox_dark_soft.theme.json"
},
"HiberbeeDark.theme.json": { "HiberbeeDark.theme.json": {
"name": "Hiberbee Dark", "name": "Hiberbee Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatHiberbeeDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Hiberbee.LICENSE.txt", "licenseFile": "Hiberbee.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12118-hiberbee-theme",
"sourceCodeUrl": "https://github.com/Hiberbee/themes", "sourceCodeUrl": "https://github.com/Hiberbee/themes",
"sourceCodePath": "blob/latest/src/intellij/src/main/resources/themes/HiberbeeDark.theme.json" "sourceCodePath": "blob/latest/src/intellij/src/main/resources/themes/HiberbeeDark.theme.json"
}, },
"HighContrast.theme.json": { "HighContrast.theme.json": {
"name": "High Contrast", "name": "High contrast",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatHighContrastIJTheme", "license": "MIT",
"license": "Apache License 2.0",
"licenseFile": "HighContrast.LICENSE.txt", "licenseFile": "HighContrast.LICENSE.txt",
"sourceCodeUrl": "https://github.com/JetBrains/intellij-community", "sourceCodeUrl": "https://github.com/OlyaB/HighContrastTheme",
"sourceCodePath": "blob/master/platform/platform-resources/src/themes/HighContrast.theme.json" "sourceCodePath": "blob/master/src/HighContrast.theme.json"
}, },
"LightFlatTheme.theme.json": { "LightFlatTheme.theme.json": {
"name": "Light Flat", "name": "Light Flat",
"license": "MIT", "license": "MIT",
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme",
"licenseFile": "LightFlatTheme.LICENSE.txt", "licenseFile": "LightFlatTheme.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12169-light-flat-theme",
"sourceCodeUrl": "https://github.com/nerzhulart/LightFlatTheme", "sourceCodeUrl": "https://github.com/nerzhulart/LightFlatTheme",
"sourceCodePath": "blob/master/src/LightFlatTheme.theme.json" "sourceCodePath": "blob/master/src/LightFlatTheme.theme.json"
}, },
"MaterialTheme.theme.json": { "MaterialTheme.theme.json": {
"name": "Material Design Dark", "name": "Material Design Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "MaterialTheme.LICENSE.txt", "licenseFile": "MaterialTheme.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12134-material-design-dark-theme",
"sourceCodeUrl": "https://github.com/xinkunZ/NotReallyMDTheme", "sourceCodeUrl": "https://github.com/xinkunZ/NotReallyMDTheme",
"sourceCodePath": "blob/master/src/main/resources/MaterialTheme.theme.json" "sourceCodePath": "blob/master/src/main/resources/MaterialTheme.theme.json"
}, },
"Monocai.theme.json": { "Monocai.theme.json": {
"name": "Monocai", "name": "Monocai",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatMonocaiIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Monocai.LICENSE.txt", "licenseFile": "Monocai.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12163-monocai-color-theme", "sourceCodeUrl": "https://github.com/bmikaili/intellij-monocai-theme",
"sourceCodeUrl": "https://github.com/TheEggi/intellij-monocai-theme",
"sourceCodePath": "blob/master/resources/Monocai.theme.json" "sourceCodePath": "blob/master/resources/Monocai.theme.json"
}, },
"Monokai_Pro.default.theme.json": { "Monokai_Pro.default.theme.json": {
"name": "Monokai Pro", "name": "Monokai Pro",
"discontinued": true,
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatMonokaiProIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Monokai_Pro.LICENSE.txt", "licenseFile": "Monokai_Pro.LICENSE.txt",
"sourceCodeUrl": "https://github.com/subtheme-dev/monokai-pro" "sourceCodeUrl": "https://github.com/subtheme-dev/monokai-pro"
@@ -215,28 +188,22 @@
"nord.theme.json": { "nord.theme.json": {
"name": "Nord", "name": "Nord",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatNordIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "nord.LICENSE.txt", "licenseFile": "nord.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/10321-nord", "sourceCodeUrl": "https://github.com/arcticicestudio/nord-jetbrains",
"sourceCodeUrl": "https://github.com/nordtheme/jetbrains",
"sourceCodePath": "blob/main/src/nord.theme.json" "sourceCodePath": "blob/main/src/nord.theme.json"
}, },
"one_dark.theme.json": { "one_dark.theme.json": {
"name": "One Dark", "name": "One Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatOneDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "one_dark.LICENSE.txt", "licenseFile": "one_dark.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/11938-one-dark-theme",
"sourceCodeUrl": "https://github.com/one-dark/jetbrains-one-dark-theme", "sourceCodeUrl": "https://github.com/one-dark/jetbrains-one-dark-theme",
"sourceCodePath": "blob/master/buildSrc/templates/oneDark.template.theme.json" "sourceCodePath": "blob/master/buildSrc/templates/oneDark.template.theme.json"
}, },
"SolarizedDark.theme.json": { "SolarizedDark.theme.json": {
"name": "Solarized Dark", "name": "Solarized Dark",
"discontinued": true,
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatSolarizedDarkIJTheme",
"license": "The Unlicense", "license": "The Unlicense",
"licenseFile": "Solarized.LICENSE.txt", "licenseFile": "Solarized.LICENSE.txt",
"sourceCodeUrl": "https://github.com/4lex4/intellij-platform-solarized", "sourceCodeUrl": "https://github.com/4lex4/intellij-platform-solarized",
@@ -244,8 +211,6 @@
}, },
"SolarizedLight.theme.json": { "SolarizedLight.theme.json": {
"name": "Solarized Light", "name": "Solarized Light",
"discontinued": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatSolarizedLightIJTheme",
"license": "The Unlicense", "license": "The Unlicense",
"licenseFile": "Solarized.LICENSE.txt", "licenseFile": "Solarized.LICENSE.txt",
"sourceCodeUrl": "https://github.com/4lex4/intellij-platform-solarized", "sourceCodeUrl": "https://github.com/4lex4/intellij-platform-solarized",
@@ -254,30 +219,24 @@
"Spacegray.theme.json": { "Spacegray.theme.json": {
"name": "Spacegray", "name": "Spacegray",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatSpacegrayIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Spacegray.LICENSE.txt", "licenseFile": "Spacegray.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12122-spacegray-theme",
"sourceCodeUrl": "https://github.com/mturlo/intellij-spacegray", "sourceCodeUrl": "https://github.com/mturlo/intellij-spacegray",
"sourceCodePath": "blob/master/src/Spacegray.theme.json" "sourceCodePath": "blob/master/src/Spacegray.theme.json"
}, },
"vuesion_theme.theme.json": { "vuesion_theme.theme.json": {
"name": "Vuesion", "name": "Vuesion",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatVuesionIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "vuesion_theme.LICENSE.txt", "licenseFile": "vuesion_theme.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/12226-vuesion-theme",
"sourceCodeUrl": "https://github.com/vuesion/intellij-theme", "sourceCodeUrl": "https://github.com/vuesion/intellij-theme",
"sourceCodePath": "blob/master/resources/META-INF/vuesion_theme.theme.json" "sourceCodePath": "blob/master/resources/META-INF/vuesion_theme.theme.json"
}, },
"Xcode-Dark.theme.json": { "Xcode-Dark.theme.json": {
"name": "Xcode-Dark", "name": "Xcode-Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.FlatXcodeDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "Xcode-Dark.LICENSE.txt", "licenseFile": "Xcode-Dark.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/13106-xcode-dark-theme",
"sourceCodeUrl": "https://github.com/antelle/intellij-xcode-dark-theme", "sourceCodeUrl": "https://github.com/antelle/intellij-xcode-dark-theme",
"sourceCodePath": "blob/master/resources/Xcode-Dark.theme.json" "sourceCodePath": "blob/master/resources/Xcode-Dark.theme.json"
}, },
@@ -285,166 +244,132 @@
"material-theme-ui-lite/Arc Dark.theme.json": { "material-theme-ui-lite/Arc Dark.theme.json": {
"name": "Material Theme UI Lite / Arc Dark", "name": "Material Theme UI Lite / Arc Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTArcDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Arc Dark.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Arc Dark.theme.json"
}, },
"material-theme-ui-lite/Atom One Dark.theme.json": { "material-theme-ui-lite/Atom One Dark.theme.json": {
"name": "Material Theme UI Lite / Atom One Dark", "name": "Material Theme UI Lite / Atom One Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Dark.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Dark.theme.json"
}, },
"material-theme-ui-lite/Atom One Light.theme.json": { "material-theme-ui-lite/Atom One Light.theme.json": {
"name": "Material Theme UI Lite / Atom One Light", "name": "Material Theme UI Lite / Atom One Light",
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneLightIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Light.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Atom One Light.theme.json"
}, },
"material-theme-ui-lite/Dracula.theme.json": { "material-theme-ui-lite/Dracula.theme.json": {
"name": "Material Theme UI Lite / Dracula", "name": "Material Theme UI Lite / Dracula",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTDraculaIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Dracula.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Dracula.theme.json"
}, },
"material-theme-ui-lite/GitHub.theme.json": { "material-theme-ui-lite/GitHub.theme.json": {
"name": "Material Theme UI Lite / GitHub", "name": "Material Theme UI Lite / GitHub",
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub.theme.json"
}, },
"material-theme-ui-lite/GitHub Dark.theme.json": { "material-theme-ui-lite/GitHub Dark.theme.json": {
"name": "Material Theme UI Lite / GitHub Dark", "name": "Material Theme UI Lite / GitHub Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub Dark.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/GitHub Dark.theme.json"
}, },
"material-theme-ui-lite/Light Owl.theme.json": { "material-theme-ui-lite/Light Owl.theme.json": {
"name": "Material Theme UI Lite / Light Owl", "name": "Material Theme UI Lite / Light Owl",
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTLightOwlIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Light Owl.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Light Owl.theme.json"
}, },
"material-theme-ui-lite/Material Darker.theme.json": { "material-theme-ui-lite/Material Darker.theme.json": {
"name": "Material Theme UI Lite / Material Darker", "name": "Material Theme UI Lite / Material Darker",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDarkerIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Darker.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Darker.theme.json"
}, },
"material-theme-ui-lite/Material Deep Ocean.theme.json": { "material-theme-ui-lite/Material Deep Ocean.theme.json": {
"name": "Material Theme UI Lite / Material Deep Ocean", "name": "Material Theme UI Lite / Material Deep Ocean",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDeepOceanIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Deep Ocean.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Deep Ocean.theme.json"
}, },
"material-theme-ui-lite/Material Lighter.theme.json": { "material-theme-ui-lite/Material Lighter.theme.json": {
"name": "Material Theme UI Lite / Material Lighter", "name": "Material Theme UI Lite / Material Lighter",
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialLighterIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Lighter.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Lighter.theme.json"
}, },
"material-theme-ui-lite/Material Oceanic.theme.json": { "material-theme-ui-lite/Material Oceanic.theme.json": {
"name": "Material Theme UI Lite / Material Oceanic", "name": "Material Theme UI Lite / Material Oceanic",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialOceanicIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Oceanic.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Oceanic.theme.json"
}, },
"material-theme-ui-lite/Material Palenight.theme.json": { "material-theme-ui-lite/Material Palenight.theme.json": {
"name": "Material Theme UI Lite / Material Palenight", "name": "Material Theme UI Lite / Material Palenight",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialPalenightIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Palenight.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Material Palenight.theme.json"
}, },
"material-theme-ui-lite/Monokai Pro.theme.json": { "material-theme-ui-lite/Monokai Pro.theme.json": {
"name": "Material Theme UI Lite / Monokai Pro", "name": "Material Theme UI Lite / Monokai Pro",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMonokaiProIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Monokai Pro.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Monokai Pro.theme.json"
}, },
"material-theme-ui-lite/Moonlight.theme.json": { "material-theme-ui-lite/Moonlight.theme.json": {
"name": "Material Theme UI Lite / Moonlight", "name": "Material Theme UI Lite / Moonlight",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMoonlightIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Moonlight.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Moonlight.theme.json"
}, },
"material-theme-ui-lite/Night Owl.theme.json": { "material-theme-ui-lite/Night Owl.theme.json": {
"name": "Material Theme UI Lite / Night Owl", "name": "Material Theme UI Lite / Night Owl",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTNightOwlIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Night Owl.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Night Owl.theme.json"
}, },
"material-theme-ui-lite/Solarized Dark.theme.json": { "material-theme-ui-lite/Solarized Dark.theme.json": {
"name": "Material Theme UI Lite / Solarized Dark", "name": "Material Theme UI Lite / Solarized Dark",
"dark": true, "dark": true,
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedDarkIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Dark.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Dark.theme.json"
}, },
"material-theme-ui-lite/Solarized Light.theme.json": { "material-theme-ui-lite/Solarized Light.theme.json": {
"name": "Material Theme UI Lite / Solarized Light", "name": "Material Theme UI Lite / Solarized Light",
"lafClassName": "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedLightIJTheme",
"license": "MIT", "license": "MIT",
"licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt", "licenseFile": "material-theme-ui-lite/Material Theme UI Lite.LICENSE.txt",
"pluginUrl": "https://plugins.jetbrains.com/plugin/8006-material-theme-ui", "sourceCodeUrl": "https://github.com/mallowigi/material-theme-ui-lite",
"sourceCodeUrl": "https://github.com/AtomMaterialUI/material-theme-ui-lite",
"sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Light.theme.json" "sourceCodePath": "blob/master/src/main/resources/themes/regular/Solarized Light.theme.json"
} }
} }

View File

@@ -1,7 +1,4 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

View File

@@ -41,11 +41,6 @@ If SVG classes are used, `jsvg-<version>.jar` is also required:
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.weisj/jsvg/badge.svg?style=flat-square&color=007ec6)](https://maven-badges.herokuapp.com/maven-central/com.github.weisj/jsvg) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.weisj/jsvg/badge.svg?style=flat-square&color=007ec6)](https://maven-badges.herokuapp.com/maven-central/com.github.weisj/jsvg)
Supported JSVG versions:
- FlatLaf 3.6.1+ supports JSVG 1.6.0 and later.
- FlatLaf 3.6- supports only JSVG 1.x (but not 2.x).
Tools Tools
----- -----

View File

@@ -25,7 +25,6 @@ import java.awt.Image;
import java.awt.Paint; import java.awt.Paint;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Dimension2D;
import java.awt.LinearGradientPaint; import java.awt.LinearGradientPaint;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.RGBImageFilter; import java.awt.image.RGBImageFilter;
@@ -53,7 +52,7 @@ import com.formdev.flatlaf.util.MultiResolutionImageSupport;
import com.formdev.flatlaf.util.SoftCache; import com.formdev.flatlaf.util.SoftCache;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import com.github.weisj.jsvg.SVGDocument; import com.github.weisj.jsvg.SVGDocument;
import com.github.weisj.jsvg.parser.LoaderContext; import com.github.weisj.jsvg.geometry.size.FloatSize;
import com.github.weisj.jsvg.parser.SVGLoader; import com.github.weisj.jsvg.parser.SVGLoader;
/** /**
@@ -272,7 +271,7 @@ public class FlatSVGIcon
this( null, -1, -1, 1, false, null, null ); this( null, -1, -1, 1, false, null, null );
try( InputStream in2 = in ) { try( InputStream in2 = in ) {
document = svgLoader.load( in2, null, LoaderContext.createDefault() ); document = svgLoader.load( in2 );
if( document == null ) { if( document == null ) {
loadFailed = true; loadFailed = true;
@@ -621,9 +620,9 @@ public class FlatSVGIcon
UIScale.scaleGraphics( g ); UIScale.scaleGraphics( g );
if( width > 0 || height > 0 ) { if( width > 0 || height > 0 ) {
Dimension2D svgSize = document.size(); FloatSize svgSize = document.size();
double sx = (width > 0) ? width / svgSize.getWidth() : 1; double sx = (width > 0) ? width / svgSize.width : 1;
double sy = (height > 0) ? height / svgSize.getHeight() : 1; double sy = (height > 0) ? height / svgSize.height : 1;
if( sx != 1 || sy != 1 ) if( sx != 1 || sy != 1 )
g.scale( sx, sy ); g.scale( sx, sy );
} }

View File

@@ -19,7 +19,6 @@ package com.formdev.flatlaf.extras;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.net.URL; import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
@@ -29,6 +28,7 @@ import javax.swing.JWindow;
import com.formdev.flatlaf.util.MultiResolutionImageSupport; import com.formdev.flatlaf.util.MultiResolutionImageSupport;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.github.weisj.jsvg.SVGDocument; import com.github.weisj.jsvg.SVGDocument;
import com.github.weisj.jsvg.geometry.size.FloatSize;
/** /**
* Utility methods for SVG. * Utility methods for SVG.
@@ -180,9 +180,9 @@ public class FlatSVGUtils
*/ */
public static BufferedImage svg2image( URL svgUrl, float scaleFactor ) { public static BufferedImage svg2image( URL svgUrl, float scaleFactor ) {
SVGDocument document = FlatSVGIcon.loadSVG( svgUrl ); SVGDocument document = FlatSVGIcon.loadSVG( svgUrl );
Dimension2D size = document.size(); FloatSize size = document.size();
int width = (int) (size.getWidth() * scaleFactor); int width = (int) (size.width * scaleFactor);
int height = (int) (size.getHeight() * scaleFactor); int height = (int) (size.height * scaleFactor);
return svg2image( document, width, height ); return svg2image( document, width, height );
} }
@@ -202,9 +202,9 @@ public class FlatSVGUtils
try { try {
FlatSVGIcon.setRenderingHints( g ); FlatSVGIcon.setRenderingHints( g );
Dimension2D size = document.size(); FloatSize size = document.size();
double sx = width / size.getWidth(); double sx = width / size.width;
double sy = height / size.getHeight(); double sy = height / size.height;
if( sx != 1 || sy != 1 ) if( sx != 1 || sy != 1 )
g.scale( sx, sy ); g.scale( sx, sy );

View File

@@ -215,14 +215,8 @@ TableHeader.pressedForeground = TableHeader.foreground
#---- TitlePane ---- #---- TitlePane ----
TitlePane.buttonBackground = TitlePane.background
TitlePane.buttonInactiveBackground = TitlePane.background
TitlePane.buttonHoverBackground = TitlePane.background TitlePane.buttonHoverBackground = TitlePane.background
TitlePane.buttonPressedBackground = TitlePane.background TitlePane.buttonPressedBackground = TitlePane.background
TitlePane.closeBackground = TitlePane.background
TitlePane.closeInactiveBackground = TitlePane.background
TitlePane.closeHoverBackground = TitlePane.background
TitlePane.closePressedBackground = TitlePane.background
#---- ToggleButton ---- #---- ToggleButton ----

View File

@@ -18,7 +18,7 @@
// For maven compatibility, <font-version> should be in format <major>.<minor>[.<micro>]. // For maven compatibility, <font-version> should be in format <major>.<minor>[.<micro>].
// <build-number> is optional and should be incremented only if a new release is // <build-number> is optional and should be incremented only if a new release is
// necessary, but the <font-version> has not changed. // necessary, but the <font-version> has not changed.
version = "4.1" version = "4.0"
if( !rootProject.hasProperty( "release" ) ) if( !rootProject.hasProperty( "release" ) )
version = version.toString() + "-SNAPSHOT" version = version.toString() + "-SNAPSHOT"

View File

@@ -1,7 +1,4 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

View File

@@ -58,13 +58,15 @@ Name | Class
[Gradianto Nature Green](https://github.com/thvardhan/Gradianto) | `com.formdev.flatlaf.intellijthemes.FlatGradiantoNatureGreenIJTheme` [Gradianto Nature Green](https://github.com/thvardhan/Gradianto) | `com.formdev.flatlaf.intellijthemes.FlatGradiantoNatureGreenIJTheme`
[Gray](https://github.com/OlyaB/GreyTheme) | `com.formdev.flatlaf.intellijthemes.FlatGrayIJTheme` [Gray](https://github.com/OlyaB/GreyTheme) | `com.formdev.flatlaf.intellijthemes.FlatGrayIJTheme`
[Gruvbox Dark Hard](https://github.com/Vincent-P/gruvbox-intellij-theme) | `com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkHardIJTheme` [Gruvbox Dark Hard](https://github.com/Vincent-P/gruvbox-intellij-theme) | `com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkHardIJTheme`
[Gruvbox Dark Medium](https://github.com/Vincent-P/gruvbox-intellij-theme) | `com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkMediumIJTheme`
[Gruvbox Dark Soft](https://github.com/Vincent-P/gruvbox-intellij-theme) | `com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkSoftIJTheme`
[Hiberbee Dark](https://github.com/Hiberbee/themes) | `com.formdev.flatlaf.intellijthemes.FlatHiberbeeDarkIJTheme` [Hiberbee Dark](https://github.com/Hiberbee/themes) | `com.formdev.flatlaf.intellijthemes.FlatHiberbeeDarkIJTheme`
[High Contrast](https://github.com/JetBrains/intellij-community) | `com.formdev.flatlaf.intellijthemes.FlatHighContrastIJTheme` [High contrast](https://github.com/OlyaB/HighContrastTheme) | `com.formdev.flatlaf.intellijthemes.FlatHighContrastIJTheme`
[Light Flat](https://github.com/nerzhulart/LightFlatTheme) | `com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme` [Light Flat](https://github.com/nerzhulart/LightFlatTheme) | `com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme`
[Material Design Dark](https://github.com/xinkunZ/NotReallyMDTheme) | `com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme` [Material Design Dark](https://github.com/xinkunZ/NotReallyMDTheme) | `com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme`
[Monocai](https://github.com/TheEggi/intellij-monocai-theme) | `com.formdev.flatlaf.intellijthemes.FlatMonocaiIJTheme` [Monocai](https://github.com/bmikaili/intellij-monocai-theme) | `com.formdev.flatlaf.intellijthemes.FlatMonocaiIJTheme`
[Monokai Pro](https://github.com/subtheme-dev/monokai-pro) | `com.formdev.flatlaf.intellijthemes.FlatMonokaiProIJTheme` [Monokai Pro](https://github.com/subtheme-dev/monokai-pro) | `com.formdev.flatlaf.intellijthemes.FlatMonokaiProIJTheme`
[Nord](https://github.com/nordtheme/jetbrains) | `com.formdev.flatlaf.intellijthemes.FlatNordIJTheme` [Nord](https://github.com/arcticicestudio/nord-jetbrains) | `com.formdev.flatlaf.intellijthemes.FlatNordIJTheme`
[One Dark](https://github.com/one-dark/jetbrains-one-dark-theme) | `com.formdev.flatlaf.intellijthemes.FlatOneDarkIJTheme` [One Dark](https://github.com/one-dark/jetbrains-one-dark-theme) | `com.formdev.flatlaf.intellijthemes.FlatOneDarkIJTheme`
[Solarized Dark](https://github.com/4lex4/intellij-platform-solarized) | `com.formdev.flatlaf.intellijthemes.FlatSolarizedDarkIJTheme` [Solarized Dark](https://github.com/4lex4/intellij-platform-solarized) | `com.formdev.flatlaf.intellijthemes.FlatSolarizedDarkIJTheme`
[Solarized Light](https://github.com/4lex4/intellij-platform-solarized) | `com.formdev.flatlaf.intellijthemes.FlatSolarizedLightIJTheme` [Solarized Light](https://github.com/4lex4/intellij-platform-solarized) | `com.formdev.flatlaf.intellijthemes.FlatSolarizedLightIJTheme`
@@ -76,20 +78,20 @@ Material Theme UI Lite:
Name | Class Name | Class
-----|------ -----|------
[Arc Dark (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTArcDarkIJTheme` [Arc Dark (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatArcDarkIJTheme`
[Atom One Dark (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneDarkIJTheme` [Atom One Dark (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatAtomOneDarkIJTheme`
[Atom One Light (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneLightIJTheme` [Atom One Light (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatAtomOneLightIJTheme`
[Dracula (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTDraculaIJTheme` [Dracula (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatDraculaIJTheme`
[GitHub (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubIJTheme` [GitHub (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatGitHubIJTheme`
[GitHub Dark (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubDarkIJTheme` [GitHub Dark (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatGitHubDarkIJTheme`
[Light Owl (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTLightOwlIJTheme` [Light Owl (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatLightOwlIJTheme`
[Material Darker (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDarkerIJTheme` [Material Darker (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialDarkerIJTheme`
[Material Deep Ocean (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDeepOceanIJTheme` [Material Deep Ocean (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialDeepOceanIJTheme`
[Material Lighter (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialLighterIJTheme` [Material Lighter (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialLighterIJTheme`
[Material Oceanic (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialOceanicIJTheme` [Material Oceanic (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialOceanicIJTheme`
[Material Palenight (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialPalenightIJTheme` [Material Palenight (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialPalenightIJTheme`
[Monokai Pro (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMonokaiProIJTheme` [Monokai Pro (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMonokaiProIJTheme`
[Moonlight (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMoonlightIJTheme` [Moonlight (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMoonlightIJTheme`
[Night Owl (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTNightOwlIJTheme` [Night Owl (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatNightOwlIJTheme`
[Solarized Dark (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedDarkIJTheme` [Solarized Dark (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatSolarizedDarkIJTheme`
[Solarized Light (Material)](https://github.com/AtomMaterialUI/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedLightIJTheme` [Solarized Light (Material)](https://github.com/mallowigi/material-theme-ui-lite) | `com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatSolarizedLightIJTheme`

View File

@@ -45,8 +45,10 @@ public class FlatAllIJThemes
new FlatIJLookAndFeelInfo( "Gradianto Nature Green", "com.formdev.flatlaf.intellijthemes.FlatGradiantoNatureGreenIJTheme", true ), new FlatIJLookAndFeelInfo( "Gradianto Nature Green", "com.formdev.flatlaf.intellijthemes.FlatGradiantoNatureGreenIJTheme", true ),
new FlatIJLookAndFeelInfo( "Gray", "com.formdev.flatlaf.intellijthemes.FlatGrayIJTheme", false ), new FlatIJLookAndFeelInfo( "Gray", "com.formdev.flatlaf.intellijthemes.FlatGrayIJTheme", false ),
new FlatIJLookAndFeelInfo( "Gruvbox Dark Hard", "com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkHardIJTheme", true ), new FlatIJLookAndFeelInfo( "Gruvbox Dark Hard", "com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkHardIJTheme", true ),
new FlatIJLookAndFeelInfo( "Gruvbox Dark Medium", "com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkMediumIJTheme", true ),
new FlatIJLookAndFeelInfo( "Gruvbox Dark Soft", "com.formdev.flatlaf.intellijthemes.FlatGruvboxDarkSoftIJTheme", true ),
new FlatIJLookAndFeelInfo( "Hiberbee Dark", "com.formdev.flatlaf.intellijthemes.FlatHiberbeeDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Hiberbee Dark", "com.formdev.flatlaf.intellijthemes.FlatHiberbeeDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "High Contrast", "com.formdev.flatlaf.intellijthemes.FlatHighContrastIJTheme", true ), new FlatIJLookAndFeelInfo( "High contrast", "com.formdev.flatlaf.intellijthemes.FlatHighContrastIJTheme", true ),
new FlatIJLookAndFeelInfo( "Light Flat", "com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme", false ), new FlatIJLookAndFeelInfo( "Light Flat", "com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme", false ),
new FlatIJLookAndFeelInfo( "Material Design Dark", "com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Material Design Dark", "com.formdev.flatlaf.intellijthemes.FlatMaterialDesignDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Monocai", "com.formdev.flatlaf.intellijthemes.FlatMonocaiIJTheme", true ), new FlatIJLookAndFeelInfo( "Monocai", "com.formdev.flatlaf.intellijthemes.FlatMonocaiIJTheme", true ),
@@ -58,23 +60,23 @@ public class FlatAllIJThemes
new FlatIJLookAndFeelInfo( "Spacegray", "com.formdev.flatlaf.intellijthemes.FlatSpacegrayIJTheme", true ), new FlatIJLookAndFeelInfo( "Spacegray", "com.formdev.flatlaf.intellijthemes.FlatSpacegrayIJTheme", true ),
new FlatIJLookAndFeelInfo( "Vuesion", "com.formdev.flatlaf.intellijthemes.FlatVuesionIJTheme", true ), new FlatIJLookAndFeelInfo( "Vuesion", "com.formdev.flatlaf.intellijthemes.FlatVuesionIJTheme", true ),
new FlatIJLookAndFeelInfo( "Xcode-Dark", "com.formdev.flatlaf.intellijthemes.FlatXcodeDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Xcode-Dark", "com.formdev.flatlaf.intellijthemes.FlatXcodeDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Arc Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTArcDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Arc Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatArcDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Atom One Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Atom One Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatAtomOneDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Atom One Light (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTAtomOneLightIJTheme", false ), new FlatIJLookAndFeelInfo( "Atom One Light (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatAtomOneLightIJTheme", false ),
new FlatIJLookAndFeelInfo( "Dracula (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTDraculaIJTheme", true ), new FlatIJLookAndFeelInfo( "Dracula (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatDraculaIJTheme", true ),
new FlatIJLookAndFeelInfo( "GitHub (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubIJTheme", false ), new FlatIJLookAndFeelInfo( "GitHub (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatGitHubIJTheme", false ),
new FlatIJLookAndFeelInfo( "GitHub Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTGitHubDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "GitHub Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatGitHubDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Light Owl (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTLightOwlIJTheme", false ), new FlatIJLookAndFeelInfo( "Light Owl (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatLightOwlIJTheme", false ),
new FlatIJLookAndFeelInfo( "Material Darker (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDarkerIJTheme", true ), new FlatIJLookAndFeelInfo( "Material Darker (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialDarkerIJTheme", true ),
new FlatIJLookAndFeelInfo( "Material Deep Ocean (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialDeepOceanIJTheme", true ), new FlatIJLookAndFeelInfo( "Material Deep Ocean (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialDeepOceanIJTheme", true ),
new FlatIJLookAndFeelInfo( "Material Lighter (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialLighterIJTheme", false ), new FlatIJLookAndFeelInfo( "Material Lighter (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialLighterIJTheme", false ),
new FlatIJLookAndFeelInfo( "Material Oceanic (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialOceanicIJTheme", true ), new FlatIJLookAndFeelInfo( "Material Oceanic (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialOceanicIJTheme", true ),
new FlatIJLookAndFeelInfo( "Material Palenight (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMaterialPalenightIJTheme", true ), new FlatIJLookAndFeelInfo( "Material Palenight (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMaterialPalenightIJTheme", true ),
new FlatIJLookAndFeelInfo( "Monokai Pro (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMonokaiProIJTheme", true ), new FlatIJLookAndFeelInfo( "Monokai Pro (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMonokaiProIJTheme", true ),
new FlatIJLookAndFeelInfo( "Moonlight (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTMoonlightIJTheme", true ), new FlatIJLookAndFeelInfo( "Moonlight (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMoonlightIJTheme", true ),
new FlatIJLookAndFeelInfo( "Night Owl (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTNightOwlIJTheme", true ), new FlatIJLookAndFeelInfo( "Night Owl (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatNightOwlIJTheme", true ),
new FlatIJLookAndFeelInfo( "Solarized Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedDarkIJTheme", true ), new FlatIJLookAndFeelInfo( "Solarized Dark (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatSolarizedDarkIJTheme", true ),
new FlatIJLookAndFeelInfo( "Solarized Light (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatMTSolarizedLightIJTheme", false ), new FlatIJLookAndFeelInfo( "Solarized Light (Material)", "com.formdev.flatlaf.intellijthemes.materialthemeuilite.FlatSolarizedLightIJTheme", false ),
}; };
//---- class FlatIJLookAndFeelInfo ---------------------------------------- //---- class FlatIJLookAndFeelInfo ----------------------------------------

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2020 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.intellijthemes;
//
// DO NOT MODIFY
// Generated with com.formdev.flatlaf.demo.intellijthemes.IJThemesClassGenerator
//
import com.formdev.flatlaf.IntelliJTheme;
/**
* @author Karl Tauber
*/
public class FlatGruvboxDarkMediumIJTheme
extends IntelliJTheme.ThemeLaf
{
public static final String NAME = "Gruvbox Dark Medium";
public static boolean setup() {
try {
return setup( new FlatGruvboxDarkMediumIJTheme() );
} catch( RuntimeException ex ) {
return false;
}
}
public static void installLafInfo() {
installLafInfo( NAME, FlatGruvboxDarkMediumIJTheme.class );
}
public FlatGruvboxDarkMediumIJTheme() {
super( Utils.loadTheme( "gruvbox_dark_medium.theme.json" ) );
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2020 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.intellijthemes;
//
// DO NOT MODIFY
// Generated with com.formdev.flatlaf.demo.intellijthemes.IJThemesClassGenerator
//
import com.formdev.flatlaf.IntelliJTheme;
/**
* @author Karl Tauber
*/
public class FlatGruvboxDarkSoftIJTheme
extends IntelliJTheme.ThemeLaf
{
public static final String NAME = "Gruvbox Dark Soft";
public static boolean setup() {
try {
return setup( new FlatGruvboxDarkSoftIJTheme() );
} catch( RuntimeException ex ) {
return false;
}
}
public static void installLafInfo() {
installLafInfo( NAME, FlatGruvboxDarkSoftIJTheme.class );
}
public FlatGruvboxDarkSoftIJTheme() {
super( Utils.loadTheme( "gruvbox_dark_soft.theme.json" ) );
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -29,7 +29,7 @@ import com.formdev.flatlaf.IntelliJTheme;
public class FlatHighContrastIJTheme public class FlatHighContrastIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "High Contrast"; public static final String NAME = "High contrast";
public static boolean setup() { public static boolean setup() {
try { try {

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTArcDarkIJTheme public class FlatArcDarkIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "Arc Dark (Material)"; public static final String NAME = "Arc Dark (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTArcDarkIJTheme() ); return setup( new FlatArcDarkIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTArcDarkIJTheme.class ); installLafInfo( NAME, FlatArcDarkIJTheme.class );
} }
public FlatMTArcDarkIJTheme() { public FlatArcDarkIJTheme() {
super( Utils.loadTheme( "Arc Dark.theme.json" ) ); super( Utils.loadTheme( "Arc Dark.theme.json" ) );
} }

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTAtomOneDarkIJTheme public class FlatAtomOneDarkIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "Atom One Dark (Material)"; public static final String NAME = "Atom One Dark (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTAtomOneDarkIJTheme() ); return setup( new FlatAtomOneDarkIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTAtomOneDarkIJTheme.class ); installLafInfo( NAME, FlatAtomOneDarkIJTheme.class );
} }
public FlatMTAtomOneDarkIJTheme() { public FlatAtomOneDarkIJTheme() {
super( Utils.loadTheme( "Atom One Dark.theme.json" ) ); super( Utils.loadTheme( "Atom One Dark.theme.json" ) );
} }

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTAtomOneLightIJTheme public class FlatAtomOneLightIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "Atom One Light (Material)"; public static final String NAME = "Atom One Light (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTAtomOneLightIJTheme() ); return setup( new FlatAtomOneLightIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTAtomOneLightIJTheme.class ); installLafInfo( NAME, FlatAtomOneLightIJTheme.class );
} }
public FlatMTAtomOneLightIJTheme() { public FlatAtomOneLightIJTheme() {
super( Utils.loadTheme( "Atom One Light.theme.json" ) ); super( Utils.loadTheme( "Atom One Light.theme.json" ) );
} }

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTDraculaIJTheme public class FlatDraculaIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "Dracula (Material)"; public static final String NAME = "Dracula (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTDraculaIJTheme() ); return setup( new FlatDraculaIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTDraculaIJTheme.class ); installLafInfo( NAME, FlatDraculaIJTheme.class );
} }
public FlatMTDraculaIJTheme() { public FlatDraculaIJTheme() {
super( Utils.loadTheme( "Dracula.theme.json" ) ); super( Utils.loadTheme( "Dracula.theme.json" ) );
} }

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTGitHubDarkIJTheme public class FlatGitHubDarkIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "GitHub Dark (Material)"; public static final String NAME = "GitHub Dark (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTGitHubDarkIJTheme() ); return setup( new FlatGitHubDarkIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTGitHubDarkIJTheme.class ); installLafInfo( NAME, FlatGitHubDarkIJTheme.class );
} }
public FlatMTGitHubDarkIJTheme() { public FlatGitHubDarkIJTheme() {
super( Utils.loadTheme( "GitHub Dark.theme.json" ) ); super( Utils.loadTheme( "GitHub Dark.theme.json" ) );
} }

View File

@@ -26,24 +26,24 @@ import com.formdev.flatlaf.IntelliJTheme;
/** /**
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMTGitHubIJTheme public class FlatGitHubIJTheme
extends IntelliJTheme.ThemeLaf extends IntelliJTheme.ThemeLaf
{ {
public static final String NAME = "GitHub (Material)"; public static final String NAME = "GitHub (Material)";
public static boolean setup() { public static boolean setup() {
try { try {
return setup( new FlatMTGitHubIJTheme() ); return setup( new FlatGitHubIJTheme() );
} catch( RuntimeException ex ) { } catch( RuntimeException ex ) {
return false; return false;
} }
} }
public static void installLafInfo() { public static void installLafInfo() {
installLafInfo( NAME, FlatMTGitHubIJTheme.class ); installLafInfo( NAME, FlatGitHubIJTheme.class );
} }
public FlatMTGitHubIJTheme() { public FlatGitHubIJTheme() {
super( Utils.loadTheme( "GitHub.theme.json" ) ); super( Utils.loadTheme( "GitHub.theme.json" ) );
} }

Some files were not shown because too many files have changed in this diff Show More