Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddf9ed06ab | ||
|
|
1907f80024 | ||
|
|
8c0ccdd227 | ||
|
|
dc098025b6 | ||
|
|
c11222b5c7 | ||
|
|
03bc6eb69b | ||
|
|
1aa339de02 | ||
|
|
531bb2a968 | ||
|
|
800dbf3ba9 | ||
|
|
ff545e6ecd | ||
|
|
961fe38c7e | ||
|
|
19426394e2 | ||
|
|
069a4e8f0b | ||
|
|
a76b02b828 | ||
|
|
fbb9bf5f0c | ||
|
|
f632c355e8 | ||
|
|
e75caf5833 | ||
|
|
b0c8f2cefd | ||
|
|
2136d9f13d | ||
|
|
83fdeb7e0c | ||
|
|
26c77b3118 | ||
|
|
578d445ecb | ||
|
|
3bbc9517af | ||
|
|
a4d7f278cf | ||
|
|
bf0ffc6ac2 | ||
|
|
ace07cd9cb | ||
|
|
a341179426 | ||
|
|
298f0dfd63 | ||
|
|
b8f953cd26 | ||
|
|
a9cfe69ba7 | ||
|
|
b3e0b99e8d | ||
|
|
5bd40baed2 | ||
|
|
d3a70b8bb2 | ||
|
|
71e698603d | ||
|
|
659ead903c | ||
|
|
070c435f40 | ||
|
|
b668a526e3 | ||
|
|
01287d0669 | ||
|
|
ff481d759f | ||
|
|
71248f1708 | ||
|
|
0a0f834f23 | ||
|
|
06cad7ecd8 | ||
|
|
ceba3e2f95 | ||
|
|
61c2fd8794 | ||
|
|
db933fee4f | ||
|
|
2656c2dc40 | ||
|
|
01cfe33865 | ||
|
|
d79a31cc79 | ||
|
|
9efab8b892 | ||
|
|
aae845247a | ||
|
|
3f45a9a75f | ||
|
|
c9016155ae | ||
|
|
1019e8f4af | ||
|
|
8e423b4552 | ||
|
|
0e288c955c | ||
|
|
465dc8a66c | ||
|
|
7e5c599cc0 | ||
|
|
a961001a4b | ||
|
|
0a181f6407 | ||
|
|
27a347db34 | ||
|
|
b228dbb2df | ||
|
|
09cffc4340 | ||
|
|
e79880d305 | ||
|
|
34266761d1 | ||
|
|
77f17eaa3e | ||
|
|
ac70342cb3 | ||
|
|
d2f16dcaf3 | ||
|
|
abcce2bf68 | ||
|
|
514487074b | ||
|
|
f014e2473f | ||
|
|
80981f7027 | ||
|
|
8e6e971b51 | ||
|
|
4bd3b889dc | ||
|
|
464787dc1e | ||
|
|
a2541a9659 | ||
|
|
099dd87241 | ||
|
|
38eb914420 | ||
|
|
162215b1cf | ||
|
|
c6883f7a92 | ||
|
|
584286b794 | ||
|
|
a48713b7ca | ||
|
|
8f10c2d8bf | ||
|
|
5c0de9aa1c | ||
|
|
5553fd6538 | ||
|
|
e3ed47b37c | ||
|
|
976353d770 | ||
|
|
6fc216dff5 | ||
|
|
3f3961d255 | ||
|
|
875637bc6d | ||
|
|
395333cb3d | ||
|
|
870d039541 | ||
|
|
e8c8bece3f | ||
|
|
bd2f5dd6fe | ||
|
|
73f78d47ae | ||
|
|
8f60755f02 | ||
|
|
44c455419b | ||
|
|
129bc9b3ae | ||
|
|
08ba7dd065 | ||
|
|
dd2cf50a39 | ||
|
|
06eeced5b2 | ||
|
|
be23e5709d | ||
|
|
2735185eb9 | ||
|
|
41dd0acfa3 | ||
|
|
115a2df2b0 | ||
|
|
fcbb3aeed1 | ||
|
|
e9cb85127a | ||
|
|
c9c703fe98 | ||
|
|
0141dfbea2 | ||
|
|
fb7dafbc39 | ||
|
|
0660f9a511 | ||
|
|
a39ae5a8c5 | ||
|
|
03e22e3dbf | ||
|
|
d5e9fd0e5c | ||
|
|
141138ebea | ||
|
|
9026efeb26 | ||
|
|
2ab023beb0 | ||
|
|
8e471fd720 | ||
|
|
13cbbd8bc1 | ||
|
|
b08ccc9767 | ||
|
|
801a7023a4 | ||
|
|
dd06b554da | ||
|
|
23f0504b30 | ||
|
|
262d172cde | ||
|
|
be81cb7876 | ||
|
|
aaf9bd33cb | ||
|
|
7381e2141f | ||
|
|
3923d941c1 | ||
|
|
37ecd9bd4f | ||
|
|
2250185487 | ||
|
|
73cb63c9f9 | ||
|
|
f61f6b6006 | ||
|
|
a8f659f2ac | ||
|
|
a878ebc368 | ||
|
|
8ee6588d46 | ||
|
|
7c25f087fb | ||
|
|
d0b0f098d9 |
@@ -5,7 +5,7 @@ jdk:
|
||||
- openjdk8
|
||||
- openjdk9
|
||||
- openjdk11
|
||||
- openjdk13
|
||||
- openjdk14
|
||||
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
|
||||
74
CHANGELOG.md
@@ -1,6 +1,80 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 0.35
|
||||
|
||||
- Added drop shadows to popup menus, combobox popups, tooltips and internal
|
||||
frames. (issue #94)
|
||||
- Support different component border colors to indicate errors, warnings or
|
||||
custom state (set client property `JComponent.outline` to `error`, `warning`
|
||||
or any `java.awt.Color`).
|
||||
- Button and ToggleButton: Support round button style (set client property
|
||||
`JButton.buttonType` to `roundRect`).
|
||||
- ComboBox, Spinner and TextField: Support round border style (set client
|
||||
property `JComponent.roundRect` to `true`).
|
||||
- Paint nicely rounded buttons, comboboxes, spinners and text fields when
|
||||
setting `Button.arc`, `Component.arc` or `TextComponent.arc` to a large value
|
||||
(e.g. 1000).
|
||||
- Added Java 9 module descriptor to `flatlaf-extras-<version>.jar` and
|
||||
`flatlaf-swingx-<version>.jar`.
|
||||
- CheckBox and RadioButton: Flag `opaque` is no longer ignored when checkbox or
|
||||
radio button is used as table cell renderer. (issue #77)
|
||||
- FileChooser: Use system icons. (issue #100)
|
||||
- FileChooser: Fixed missing labels in file chooser when running on Java 9 or
|
||||
later. (issue #98)
|
||||
- PasswordField: Do not apply minimum width if `columns` property is greater
|
||||
than zero.
|
||||
|
||||
|
||||
## 0.34
|
||||
|
||||
- Menus: New menu item renderer brings stable left margins, right aligned
|
||||
accelerators and larger gap between text and accelerator. This makes menus
|
||||
look more modern and more similar to native platform menus.
|
||||
- New underline menu selection style that displays selected menu items similar
|
||||
to tabs (to enable use `UIManager.put( "MenuItem.selectionType", "underline"
|
||||
);`).
|
||||
- Menus: Fixed text color of selected menu items that use HTML. (issue #87)
|
||||
- Menus: On Windows, pressing <kbd>F10</kbd> now activates the menu bar without
|
||||
showing a menu popup (as usual on Windows platform). On other platforms the
|
||||
first menu popup is shown.
|
||||
- Menus: On Windows, releasing <kbd>Alt</kbd> key now activates the menu bar (as
|
||||
usual on Windows platform). (issue #43)
|
||||
- Menus: Fixed inconsistent left padding in menu items. (issue #3)
|
||||
- Menus: Fixed: Setting `iconTextGap` property on a menu item did increase left
|
||||
and right margins. (issue #54)
|
||||
- Hide mnemonics if window is deactivated (e.g. <kbd>Alt+Tab</kbd> to another
|
||||
window). (issue #43)
|
||||
- macOS: Enabled drop shadows for popup menus and combobox popups. (issue #94)
|
||||
- macOS: Fixed NPE if using `JMenuBar` in `JInternalFrame` and macOS screen menu
|
||||
bar is enabled (with `-Dapple.laf.useScreenMenuBar=true`). (issue #90)
|
||||
|
||||
|
||||
## 0.33
|
||||
|
||||
- Improved creation of disabled grayscale icons used in disabled buttons, labels
|
||||
and tabs. They now have more contrast and are lighter in light themes and
|
||||
darker in dark themes. (issue #70)
|
||||
- IntelliJ Themes: Fixed ComboBox size and Spinner border in all Material UI
|
||||
Lite themes and limit tree row height in all Material UI Lite themes and some
|
||||
other themes.
|
||||
- IntelliJ Themes: Material UI Lite themes did not work when using
|
||||
[IntelliJ Themes Pack](flatlaf-intellij-themes) addon. (PR #88, issue #89)
|
||||
- IntelliJ Themes: Added Java 9 module descriptor to
|
||||
`flatlaf-intellij-themes-<version>.jar`.
|
||||
|
||||
|
||||
## 0.32
|
||||
|
||||
- New [IntelliJ Themes Pack](flatlaf-intellij-themes) addon bundles many popular
|
||||
open-source 3rd party themes from JetBrains Plugins Repository into a JAR and
|
||||
provides Java classes to use them.
|
||||
- IntelliJ Themes: Fixed button and toggle button colors. (issue #86)
|
||||
- Updated IntelliJ Themes in demo to the latest versions.
|
||||
- ToggleButton: Compute selected background color based on current component
|
||||
background. (issue #32)
|
||||
|
||||
|
||||
## 0.31
|
||||
|
||||
- Focus indication border (or background) no longer hidden when temporary
|
||||
|
||||
@@ -19,7 +19,8 @@ IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||
IntelliJ Platform Themes
|
||||
------------------------
|
||||
|
||||
FlatLaf can use 3rd party themes created for IntelliJ Platform:
|
||||
FlatLaf can use 3rd party themes created for IntelliJ Platform (see
|
||||
[IntelliJ Themes Pack](flatlaf-intellij-themes)):
|
||||
|
||||

|
||||
|
||||
@@ -68,6 +69,8 @@ docs).
|
||||
Addons
|
||||
------
|
||||
|
||||
- [IntelliJ Themes Pack](flatlaf-intellij-themes)
|
||||
- [Extras](flatlaf-extras)
|
||||
- [SwingX](flatlaf-swingx)
|
||||
- [JIDE Common Layer](flatlaf-jide-oss)
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "0.31"
|
||||
val developmentVersion = "0.32-SNAPSHOT"
|
||||
val releaseVersion = "0.35"
|
||||
val developmentVersion = "0.36-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
|
||||
34
buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
// required for kotlin-dsl or embedded-kotlin plugins
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// NOTE: keep plugin versions in sync with settings.gradle.kts
|
||||
|
||||
// "com.jfrog.bintray" plugin
|
||||
implementation( "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4" )
|
||||
|
||||
// "com.jfrog.artifactory" plugin
|
||||
implementation( "org.jfrog.buildinfo:build-info-extractor-gradle:4.13.0" )
|
||||
}
|
||||
80
buildSrc/src/main/java/ReorderJarEntries.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Reorders entries in a JAR file so that .properties files are placed before .class files,
|
||||
* which is necessary to workaround an issue in NetBeans 11.3 (and older).
|
||||
* See issues #13 and #93.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class ReorderJarEntries
|
||||
{
|
||||
public static void reorderJarEntries( File jarFile )
|
||||
throws IOException
|
||||
{
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream( (int) jarFile.length() + 1000 );
|
||||
|
||||
try( ZipOutputStream zipOutStream = new ZipOutputStream( outStream ) ) {
|
||||
// 1st pass: copy .properties files
|
||||
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
||||
|
||||
// 2st pass: copy other files
|
||||
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
||||
}
|
||||
|
||||
// replace JAR
|
||||
Files.write( jarFile.toPath(), outStream.toByteArray(),
|
||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING );
|
||||
}
|
||||
|
||||
private static void copyFiles( ZipOutputStream dest, File jarFile, Predicate<String> filter )
|
||||
throws IOException
|
||||
{
|
||||
try( ZipInputStream zipInputStream = new ZipInputStream( new FileInputStream( jarFile ) ) ) {
|
||||
ZipEntry entry;
|
||||
while( (entry = zipInputStream.getNextEntry()) != null ) {
|
||||
if( filter.test( entry.getName() ) ) {
|
||||
dest.putNextEntry( entry );
|
||||
copyFile( zipInputStream, dest );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFile( InputStream src, OutputStream dest )
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[8*1024];
|
||||
int len;
|
||||
while( (len = src.read( buf )) > 0 )
|
||||
dest.write( buf, 0, len );
|
||||
dest.flush();
|
||||
}
|
||||
}
|
||||
44
buildSrc/src/main/kotlin/flatlaf-java9.gradle.kts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
sourceSets {
|
||||
create( "java9" ) {
|
||||
java {
|
||||
setSrcDirs( listOf( "src/main/java9" ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
named<JavaCompile>( "compileJava9Java" ) {
|
||||
sourceCompatibility = "9"
|
||||
targetCompatibility = "9"
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes( "Multi-Release" to "true" )
|
||||
|
||||
into( "META-INF/versions/9" ) {
|
||||
from( sourceSets["java9"].output )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
buildSrc/src/main/kotlin/flatlaf-module-info.gradle.kts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
open class ModuleInfoExtension {
|
||||
var paths: ArrayList<String> = ArrayList()
|
||||
|
||||
fun dependsOn( vararg paths: String ) {
|
||||
this.paths.addAll( paths )
|
||||
}
|
||||
}
|
||||
|
||||
val extension = project.extensions.create<ModuleInfoExtension>( "flatlafModuleInfo" )
|
||||
|
||||
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
sourceSets {
|
||||
create( "module-info" ) {
|
||||
java {
|
||||
// include "src/main/java" here to get compile errors if classes are
|
||||
// used from other modules that are not specified in module dependencies
|
||||
setSrcDirs( listOf( "src/main/module-info", "src/main/java" ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
named<JavaCompile>( "compileModuleInfoJava" ) {
|
||||
sourceCompatibility = "9"
|
||||
targetCompatibility = "9"
|
||||
|
||||
dependsOn( extension.paths )
|
||||
|
||||
options.compilerArgs.add( "--module-path" )
|
||||
options.compilerArgs.add( configurations.runtimeClasspath.get().asPath )
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes( "Multi-Release" to "true" )
|
||||
|
||||
into( "META-INF/versions/9" ) {
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
buildSrc/src/main/kotlin/flatlaf-publish.gradle.kts
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
open class PublishExtension {
|
||||
var artifactId: String? = null
|
||||
var name: String? = null
|
||||
var description: String? = null
|
||||
}
|
||||
|
||||
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||
|
||||
|
||||
plugins {
|
||||
`maven-publish`
|
||||
id( "com.jfrog.bintray" )
|
||||
id( "com.jfrog.artifactory" )
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>( "maven" ) {
|
||||
afterEvaluate {
|
||||
artifactId = extension.artifactId
|
||||
}
|
||||
groupId = "com.formdev"
|
||||
|
||||
from( components["java"] )
|
||||
|
||||
pom {
|
||||
afterEvaluate {
|
||||
this@pom.name.set( extension.name )
|
||||
this@pom.description.set( extension.description )
|
||||
}
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name.set( "The Apache License, Version 2.0" )
|
||||
url.set( "https://www.apache.org/licenses/LICENSE-2.0.txt" )
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
name.set( "Karl Tauber" )
|
||||
organization.set( "FormDev Software GmbH" )
|
||||
organizationUrl.set( "https://www.formdev.com/" )
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = rootProject.extra["bintray.user"] as String?
|
||||
key = rootProject.extra["bintray.key"] as String?
|
||||
|
||||
setPublications( "maven" )
|
||||
|
||||
with( pkg ) {
|
||||
repo = "flatlaf"
|
||||
afterEvaluate {
|
||||
this@with.name = extension.artifactId
|
||||
}
|
||||
setLicenses( "Apache-2.0" )
|
||||
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
|
||||
|
||||
with( version ) {
|
||||
name = project.version.toString()
|
||||
}
|
||||
|
||||
publish = rootProject.extra["bintray.publish"] as Boolean
|
||||
dryRun = rootProject.extra["bintray.dryRun"] as Boolean
|
||||
}
|
||||
}
|
||||
|
||||
artifactory {
|
||||
setContextUrl( "https://oss.jfrog.org" )
|
||||
|
||||
publish( closureOf<org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig> {
|
||||
repository( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
setProperty( "repoKey", "oss-snapshot-local" )
|
||||
setProperty( "username", rootProject.extra["bintray.user"] as String? )
|
||||
setProperty( "password", rootProject.extra["bintray.key"] as String? )
|
||||
} )
|
||||
|
||||
defaults( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
invokeMethod( "publications", "maven" )
|
||||
setProperty( "publishArtifacts", true )
|
||||
setProperty( "publishPom", true )
|
||||
} )
|
||||
} )
|
||||
|
||||
resolve( delegateClosureOf<org.jfrog.gradle.plugin.artifactory.dsl.ResolverConfig> {
|
||||
setProperty( "repoKey", "jcenter" )
|
||||
} )
|
||||
}
|
||||
@@ -16,45 +16,22 @@
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
id( "com.jfrog.bintray" )
|
||||
id( "com.jfrog.artifactory" )
|
||||
`flatlaf-module-info`
|
||||
`flatlaf-java9`
|
||||
`flatlaf-publish`
|
||||
}
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
sourceSets {
|
||||
create( "module-info" ) {
|
||||
java {
|
||||
// include "src/main/java" here to get compile errors if classes are
|
||||
// used from other modules that are not specified in module dependencies
|
||||
setSrcDirs( listOf( "src/main/module-info", "src/main/java" ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
java {
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn(
|
||||
"sourcesJar",
|
||||
"javadocJar"
|
||||
)
|
||||
}
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
named<JavaCompile>( "compileModuleInfoJava" ) {
|
||||
sourceCompatibility = "9"
|
||||
targetCompatibility = "9"
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
doLast {
|
||||
ReorderJarEntries.reorderJarEntries( outputs.files.singleFile );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,99 +44,17 @@ tasks {
|
||||
isFailOnError = false
|
||||
}
|
||||
|
||||
register( "sourcesJar", Jar::class ) {
|
||||
named<Jar>("sourcesJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveClassifier.set( "sources" )
|
||||
|
||||
from( sourceSets.main.get().allJava )
|
||||
}
|
||||
|
||||
register( "javadocJar", Jar::class ) {
|
||||
named<Jar>("javadocJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveClassifier.set( "javadoc" )
|
||||
|
||||
from( javadoc )
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>( "maven" ) {
|
||||
artifactId = "flatlaf"
|
||||
groupId = "com.formdev"
|
||||
|
||||
from( components["java"] )
|
||||
|
||||
artifact( tasks["sourcesJar"] )
|
||||
artifact( tasks["javadocJar"] )
|
||||
|
||||
pom {
|
||||
name.set( "FlatLaf" )
|
||||
description.set( "Flat Look and Feel" )
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name.set( "The Apache License, Version 2.0" )
|
||||
url.set( "https://www.apache.org/licenses/LICENSE-2.0.txt" )
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
name.set( "Karl Tauber" )
|
||||
organization.set( "FormDev Software GmbH" )
|
||||
organizationUrl.set( "https://www.formdev.com/" )
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = rootProject.extra["bintray.user"] as String?
|
||||
key = rootProject.extra["bintray.key"] as String?
|
||||
|
||||
setPublications( "maven" )
|
||||
|
||||
with( pkg ) {
|
||||
repo = "flatlaf"
|
||||
name = "flatlaf"
|
||||
setLicenses( "Apache-2.0" )
|
||||
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
|
||||
|
||||
with( version ) {
|
||||
name = project.version.toString()
|
||||
}
|
||||
|
||||
publish = rootProject.extra["bintray.publish"] as Boolean
|
||||
dryRun = rootProject.extra["bintray.dryRun"] as Boolean
|
||||
}
|
||||
}
|
||||
|
||||
artifactory {
|
||||
setContextUrl( "https://oss.jfrog.org" )
|
||||
|
||||
publish( closureOf<org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig> {
|
||||
repository( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
setProperty( "repoKey", "oss-snapshot-local" )
|
||||
setProperty( "username", rootProject.extra["bintray.user"] as String? )
|
||||
setProperty( "password", rootProject.extra["bintray.key"] as String? )
|
||||
} )
|
||||
|
||||
defaults( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
invokeMethod( "publications", "maven" )
|
||||
setProperty( "publishArtifacts", true )
|
||||
setProperty( "publishPom", true )
|
||||
} )
|
||||
} )
|
||||
|
||||
resolve( delegateClosureOf<org.jfrog.gradle.plugin.artifactory.dsl.ResolverConfig> {
|
||||
setProperty( "repoKey", "jcenter" )
|
||||
} )
|
||||
flatlafPublish {
|
||||
artifactId = "flatlaf"
|
||||
name = "FlatLaf"
|
||||
description = "Flat Look and Feel"
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ public interface FlatClientProperties
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong> {@link #BUTTON_TYPE_SQUARE} and {@link #BUTTON_TYPE_HELP}
|
||||
* <strong>Allowed Values</strong> {@link #BUTTON_TYPE_SQUARE}, {@link #BUTTON_TYPE_ROUND_RECT},
|
||||
* {@link #BUTTON_TYPE_TAB}, {@link #BUTTON_TYPE_HELP} and {@link BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||
*/
|
||||
String BUTTON_TYPE = "JButton.buttonType";
|
||||
|
||||
@@ -43,6 +44,15 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String BUTTON_TYPE_SQUARE = "square";
|
||||
|
||||
/**
|
||||
* Paint the button with round edges.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}
|
||||
*
|
||||
* @see #BUTTON_TYPE
|
||||
*/
|
||||
String BUTTON_TYPE_ROUND_RECT = "roundRect";
|
||||
|
||||
/**
|
||||
* Paint the toggle button in tab style.
|
||||
* <p>
|
||||
@@ -61,6 +71,15 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String BUTTON_TYPE_HELP = "help";
|
||||
|
||||
/**
|
||||
* Paint the button in toolbar style.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}
|
||||
*
|
||||
* @see #BUTTON_TYPE
|
||||
*/
|
||||
String BUTTON_TYPE_TOOLBAR_BUTTON = "toolBarButton";
|
||||
|
||||
/**
|
||||
* Specifies selected state of a checkbox.
|
||||
* <p>
|
||||
@@ -93,6 +112,52 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String MINIMUM_HEIGHT = "JComponent.minimumHeight";
|
||||
|
||||
/**
|
||||
* Specifies the outline color of the component border.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton}, {@link javax.swing.JComboBox},
|
||||
* {@link javax.swing.JFormattedTextField}, {@link javax.swing.JPasswordField},
|
||||
* {@link javax.swing.JScrollPane}, {@link javax.swing.JSpinner},
|
||||
* {@link javax.swing.JTextField} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String} or {@link java.awt.Color} or {@link java.awt.Color}[2]<br>
|
||||
* <strong>Allowed Values</strong> {@link #OUTLINE_ERROR}, {@link #OUTLINE_WARNING},
|
||||
* any color (type {@link java.awt.Color}) or 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
|
||||
*/
|
||||
String OUTLINE = "JComponent.outline";
|
||||
|
||||
/**
|
||||
* Paint the component border in another color (usually reddish) to indicate an error.
|
||||
*
|
||||
* @see #OUTLINE
|
||||
*/
|
||||
String OUTLINE_ERROR = "error";
|
||||
|
||||
/**
|
||||
* Paint the component border in another color (usually yellowish) to indicate a warning.
|
||||
*
|
||||
* @see #OUTLINE
|
||||
*/
|
||||
String OUTLINE_WARNING = "warning";
|
||||
|
||||
/**
|
||||
* Paint the component with round edges.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JComboBox}, {@link javax.swing.JSpinner},
|
||||
* {@link javax.swing.JTextField}, {@link javax.swing.JFormattedTextField} and {@link javax.swing.JPasswordField}
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*/
|
||||
String COMPONENT_ROUND_RECT = "JComponent.roundRect";
|
||||
|
||||
/**
|
||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||
* or if the component is the owner of another component that is shown in a popup.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*/
|
||||
String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted";
|
||||
|
||||
/**
|
||||
* Specifies whether the progress bar has always the larger height even if no string is painted.
|
||||
* <p>
|
||||
@@ -240,4 +305,14 @@ public interface FlatClientProperties
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Color) ? (Color) value : defaultValue;
|
||||
}
|
||||
|
||||
static int clientPropertyChoice( JComponent c, String key, String... choices ) {
|
||||
Object value = c.getClientProperty( key );
|
||||
for( int i = 0; i < choices.length; i++ ) {
|
||||
if( choices[i].equals( value ) )
|
||||
return i;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ public class FlatDarculaLaf
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Flat Darcula";
|
||||
return "FlatLaf Darcula";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Flat Darcula Look and Feel";
|
||||
return "FlatLaf Darcula Look and Feel";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class FlatDarkLaf
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Flat Dark";
|
||||
return "FlatLaf Dark";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Flat Dark Look and Feel";
|
||||
return "FlatLaf Dark Look and Feel";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Default color palette for action icons and object icons.
|
||||
* <p>
|
||||
* The idea is to use only this well defined set of colors in SVG icons and
|
||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||
* <p>
|
||||
* Use the {@code *_DARK} colors only in {@code *_dark.svg} files.
|
||||
* <p>
|
||||
* The colors are based on IntelliJ Platform
|
||||
* <a href="https://jetbrains.design/intellij/principles/icons/#action-icons">Action icons</a>
|
||||
* and
|
||||
* <a href="https://jetbrains.design/intellij/principles/icons/#noun-icons">Noun icons</a>
|
||||
* <p>
|
||||
* These colors may be changed by IntelliJ Platform themes.
|
||||
* <p>
|
||||
* You may use these colors also in your application (outside of SVG icons), but do
|
||||
* not use the RGB values defined in this enum.<br>
|
||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public enum FlatIconColors
|
||||
{
|
||||
// colors for action icons
|
||||
// see https://jetbrains.design/intellij/principles/icons/#action-icons
|
||||
ACTIONS_RED ( 0xDB5860, "Actions.Red", true, false ),
|
||||
ACTIONS_RED_DARK ( 0xC75450, "Actions.Red", false, true ),
|
||||
ACTIONS_YELLOW ( 0xEDA200, "Actions.Yellow", true, false ),
|
||||
ACTIONS_YELLOW_DARK ( 0xF0A732, "Actions.Yellow", false, true ),
|
||||
ACTIONS_GREEN ( 0x59A869, "Actions.Green", true, false ),
|
||||
ACTIONS_GREEN_DARK ( 0x499C54, "Actions.Green", false, true ),
|
||||
ACTIONS_BLUE ( 0x389FD6, "Actions.Blue", true, false ),
|
||||
ACTIONS_BLUE_DARK ( 0x3592C4, "Actions.Blue", false, true ),
|
||||
ACTIONS_GREY ( 0x6E6E6E, "Actions.Grey", true, false ),
|
||||
ACTIONS_GREY_DARK ( 0xAFB1B3, "Actions.Grey", false, true ),
|
||||
ACTIONS_GREYINLINE ( 0x7F8B91, "Actions.GreyInline", true, false ),
|
||||
ACTIONS_GREYINLINE_DARK ( 0x7F8B91, "Actions.GreyInline", false, true ),
|
||||
|
||||
// colors for object icons
|
||||
// see https://jetbrains.design/intellij/principles/icons/#noun-icons
|
||||
OBJECTS_GREY ( 0x9AA7B0, "Objects.Grey" ),
|
||||
OBJECTS_BLUE ( 0x40B6E0, "Objects.Blue" ),
|
||||
OBJECTS_GREEN ( 0x62B543, "Objects.Green" ),
|
||||
OBJECTS_YELLOW ( 0xF4AF3D, "Objects.Yellow" ),
|
||||
OBJECTS_YELLOW_DARK ( 0xD9A343, "Objects.YellowDark" ),
|
||||
OBJECTS_PURPLE ( 0xB99BF8, "Objects.Purple" ),
|
||||
OBJECTS_PINK ( 0xF98B9E, "Objects.Pink" ),
|
||||
OBJECTS_RED ( 0xF26522, "Objects.Red" ),
|
||||
OBJECTS_RED_STATUS ( 0xE05555, "Objects.RedStatus" ),
|
||||
OBJECTS_GREEN_ANDROID ( 0xA4C639, "Objects.GreenAndroid" ),
|
||||
OBJECTS_BLACK_TEXT ( 0x231F20, "Objects.BlackText" );
|
||||
|
||||
public final int rgb;
|
||||
public final String key;
|
||||
|
||||
public final boolean light;
|
||||
public final boolean dark;
|
||||
|
||||
FlatIconColors( int rgb, String key ) {
|
||||
this( rgb, key, true, true );
|
||||
}
|
||||
|
||||
FlatIconColors( int rgb, String key, boolean light, boolean dark ) {
|
||||
this.rgb = rgb;
|
||||
this.key = key;
|
||||
this.light = light;
|
||||
this.dark = dark;
|
||||
}
|
||||
}
|
||||
@@ -85,8 +85,12 @@ class FlatInputMaps
|
||||
// swap to make it consistent with List and Tree
|
||||
"HOME", "selectFirstRow",
|
||||
"END", "selectLastRow",
|
||||
"shift HOME", "selectFirstRowExtendSelection",
|
||||
"shift END", "selectLastRowExtendSelection",
|
||||
mac( "ctrl HOME", null ), "selectFirstColumn",
|
||||
mac( "ctrl END", null ), "selectLastColumn"
|
||||
mac( "ctrl END", null ), "selectLastColumn",
|
||||
mac( "shift ctrl HOME", null ), "selectFirstColumnExtendSelection",
|
||||
mac( "shift ctrl END", null ), "selectLastColumnExtendSelection"
|
||||
);
|
||||
|
||||
if( !SystemInfo.IS_MAC ) {
|
||||
@@ -501,6 +505,9 @@ class FlatInputMaps
|
||||
"alt KP_LEFT", "selectParent",
|
||||
"alt KP_RIGHT", "selectChild",
|
||||
|
||||
"shift HOME", "selectFirstExtendSelection",
|
||||
"shift END", "selectLastExtendSelection",
|
||||
|
||||
"meta A", "selectAll",
|
||||
"meta C", "copy",
|
||||
"meta V", "paste",
|
||||
@@ -545,8 +552,6 @@ class FlatInputMaps
|
||||
"shift ctrl SPACE", null,
|
||||
"shift ctrl UP", null,
|
||||
"shift DELETE", null,
|
||||
"shift END", null,
|
||||
"shift HOME", null,
|
||||
"shift INSERT", null,
|
||||
"shift PAGE_DOWN", null,
|
||||
"shift PAGE_UP", null,
|
||||
|
||||
@@ -32,11 +32,11 @@ public class FlatIntelliJLaf
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Flat IntelliJ";
|
||||
return "FlatLaf IntelliJ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Flat IntelliJ Look and Feel";
|
||||
return "FlatLaf IntelliJ Look and Feel";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,18 +18,17 @@ package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Font;
|
||||
import java.awt.KeyEventPostProcessor;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.image.FilteredImageSource;
|
||||
import java.awt.image.ImageFilter;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -37,12 +36,13 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -56,6 +56,9 @@ import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicLookAndFeel;
|
||||
import javax.swing.text.StyleContext;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import com.formdev.flatlaf.ui.FlatPopupFactory;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
@@ -76,9 +79,8 @@ public abstract class FlatLaf
|
||||
private static boolean aquaLoaded;
|
||||
private static boolean updateUIPending;
|
||||
|
||||
private KeyEventPostProcessor mnemonicListener;
|
||||
private static boolean showMnemonics;
|
||||
private static WeakReference<Window> lastShowMnemonicWindow;
|
||||
private PopupFactory oldPopupFactory;
|
||||
private MnemonicHandler mnemonicHandler;
|
||||
|
||||
private Consumer<UIDefaults> postInitialization;
|
||||
|
||||
@@ -117,6 +119,26 @@ public abstract class FlatLaf
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getDisabledIcon( JComponent component, Icon icon ) {
|
||||
if( icon instanceof ImageIcon ) {
|
||||
Object grayFilter = UIManager.get( "Component.grayFilter" );
|
||||
ImageFilter filter = (grayFilter instanceof ImageFilter)
|
||||
? (ImageFilter) grayFilter
|
||||
: GrayFilter.createDisabledIconFilter( isDark() ); // fallback
|
||||
|
||||
Function<Image, Image> mapper = img -> {
|
||||
ImageProducer producer = new FilteredImageSource( img.getSource(), filter );
|
||||
return Toolkit.getDefaultToolkit().createImage( producer );
|
||||
};
|
||||
|
||||
Image image = ((ImageIcon)icon).getImage();
|
||||
return new ImageIconUIResource( MultiResolutionImageSupport.map( image, mapper ) );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if( SystemInfo.IS_MAC )
|
||||
@@ -124,12 +146,13 @@ public abstract class FlatLaf
|
||||
|
||||
super.initialize();
|
||||
|
||||
// add mnemonic listener
|
||||
mnemonicListener = e -> {
|
||||
checkShowMnemonics( e );
|
||||
return false;
|
||||
};
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( mnemonicListener );
|
||||
// install popup factory
|
||||
oldPopupFactory = PopupFactory.getSharedInstance();
|
||||
PopupFactory.setSharedInstance( new FlatPopupFactory() );
|
||||
|
||||
// install mnemonic handler
|
||||
mnemonicHandler = new MnemonicHandler();
|
||||
mnemonicHandler.install();
|
||||
|
||||
// listen to desktop property changes to update UI if system font or scaling changes
|
||||
if( SystemInfo.IS_WINDOWS ) {
|
||||
@@ -183,10 +206,16 @@ public abstract class FlatLaf
|
||||
desktopPropertyListener = null;
|
||||
}
|
||||
|
||||
// remove mnemonic listener
|
||||
if( mnemonicListener != null ) {
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor( mnemonicListener );
|
||||
mnemonicListener = null;
|
||||
// uninstall popup factory
|
||||
if( oldPopupFactory != null ) {
|
||||
PopupFactory.setSharedInstance( oldPopupFactory );
|
||||
oldPopupFactory = null;
|
||||
}
|
||||
|
||||
// uninstall mnemonic handler
|
||||
if( mnemonicHandler != null ) {
|
||||
mnemonicHandler.uninstall();
|
||||
mnemonicHandler = null;
|
||||
}
|
||||
|
||||
// restore default link color
|
||||
@@ -239,8 +268,8 @@ public abstract class FlatLaf
|
||||
public UIDefaults getDefaults() {
|
||||
UIDefaults defaults = super.getDefaults();
|
||||
|
||||
// add Metal resource bundle, which is required for FlatFileChooserUI
|
||||
defaults.addResourceBundle( "com.sun.swing.internal.plaf.metal.resources.metal" );
|
||||
// add resource bundle for localized texts
|
||||
defaults.addResourceBundle( "com.formdev.flatlaf.resources.Bundle" );
|
||||
|
||||
// initialize some defaults (for overriding) that are used in UI delegates,
|
||||
// but are not set in BasicLookAndFeel
|
||||
@@ -282,14 +311,18 @@ public abstract class FlatLaf
|
||||
// load defaults from properties
|
||||
List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading();
|
||||
if( lafClassesForDefaultsLoading != null )
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), defaults );
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), isDark(), defaults );
|
||||
else
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), defaults );
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults );
|
||||
|
||||
// use Aqua MenuBarUI if Mac screen menubar is enabled
|
||||
if( SystemInfo.IS_MAC && Boolean.getBoolean( "apple.laf.useScreenMenuBar" ) )
|
||||
if( SystemInfo.IS_MAC && Boolean.getBoolean( "apple.laf.useScreenMenuBar" ) ) {
|
||||
defaults.put( "MenuBarUI", "com.apple.laf.AquaMenuBarUI" );
|
||||
|
||||
// add defaults necessary for AquaMenuBarUI
|
||||
defaults.put( "MenuBar.backgroundPainter", BorderFactory.createEmptyBorder() );
|
||||
}
|
||||
|
||||
// initialize text antialiasing
|
||||
putAATextInfo( defaults );
|
||||
|
||||
@@ -300,6 +333,11 @@ public abstract class FlatLaf
|
||||
for( FlatDefaultsAddon addon : addons )
|
||||
addon.afterDefaultsLoading( this, defaults );
|
||||
|
||||
// add user scale factor to allow layout managers (e.g. MigLayout) to use it
|
||||
defaults.put( "laf.scaleFactor", (ActiveValue) t -> {
|
||||
return UIScale.getUserScaleFactor();
|
||||
} );
|
||||
|
||||
if( postInitialization != null ) {
|
||||
postInitialization.accept( defaults );
|
||||
postInitialization = null;
|
||||
@@ -388,30 +426,14 @@ public abstract class FlatLaf
|
||||
* <a href="https://jetbrains.design/intellij/principles/icons/#action-icons">Action icons</a>
|
||||
* and
|
||||
* <a href="https://jetbrains.design/intellij/principles/icons/#noun-icons">Noun icons</a>
|
||||
* <p>
|
||||
* These colors may be changed by IntelliJ Platform themes.
|
||||
*/
|
||||
public static void initIconColors( UIDefaults defaults, boolean dark ) {
|
||||
// colors for action icons
|
||||
// see https://jetbrains.design/intellij/principles/icons/#action-icons
|
||||
defaults.put( "Actions.Red", new ColorUIResource( !dark ? 0xDB5860 : 0xC75450 ) );
|
||||
defaults.put( "Actions.Yellow", new ColorUIResource( !dark ? 0xEDA200 : 0xF0A732 ) );
|
||||
defaults.put( "Actions.Green", new ColorUIResource( !dark ? 0x59A869 : 0x499C54 ) );
|
||||
defaults.put( "Actions.Blue", new ColorUIResource( !dark ? 0x389FD6 : 0x3592C4 ) );
|
||||
defaults.put( "Actions.Grey", new ColorUIResource( !dark ? 0x6E6E6E : 0xAFB1B3 ) );
|
||||
defaults.put( "Actions.GreyInline", new ColorUIResource( !dark ? 0x7F8B91 : 0x7F8B91 ) );
|
||||
|
||||
// colors for object icons
|
||||
// see https://jetbrains.design/intellij/principles/icons/#noun-icons
|
||||
defaults.put( "Objects.Grey", new ColorUIResource( 0x9AA7B0 ) );
|
||||
defaults.put( "Objects.Blue", new ColorUIResource( 0x40B6E0 ) );
|
||||
defaults.put( "Objects.Green", new ColorUIResource( 0x62B543 ) );
|
||||
defaults.put( "Objects.Yellow", new ColorUIResource( 0xF4AF3D ) );
|
||||
defaults.put( "Objects.YellowDark", new ColorUIResource( 0xD9A343 ) );
|
||||
defaults.put( "Objects.Purple", new ColorUIResource( 0xB99BF8 ) );
|
||||
defaults.put( "Objects.Pink", new ColorUIResource( 0xF98B9E ) );
|
||||
defaults.put( "Objects.Red", new ColorUIResource( 0xF26522 ) );
|
||||
defaults.put( "Objects.RedStatus", new ColorUIResource( 0xE05555 ) );
|
||||
defaults.put( "Objects.GreenAndroid", new ColorUIResource( 0xA4C639 ) );
|
||||
defaults.put( "Objects.BlackText", new ColorUIResource( 0x231F20 ) );
|
||||
for( FlatIconColors c : FlatIconColors.values() ) {
|
||||
if( c.light == !dark || c.dark == dark )
|
||||
defaults.put( c.key, new ColorUIResource( c.rgb ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void putAATextInfo( UIDefaults defaults ) {
|
||||
@@ -501,86 +523,15 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
public static boolean isShowMnemonics() {
|
||||
return showMnemonics || !UIManager.getBoolean( "Component.hideMnemonics" );
|
||||
return MnemonicHandler.isShowMnemonics();
|
||||
}
|
||||
|
||||
private static void checkShowMnemonics( KeyEvent e ) {
|
||||
int keyCode = e.getKeyCode();
|
||||
if( SystemInfo.IS_MAC ) {
|
||||
// Ctrl+Alt keys must be pressed on Mac
|
||||
if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED && e.isControlDown() && e.isAltDown(), e.getComponent() );
|
||||
} else {
|
||||
// Alt key must be pressed on Windows and Linux
|
||||
if( keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED, e.getComponent() );
|
||||
}
|
||||
public static void showMnemonics( Component c ) {
|
||||
MnemonicHandler.showMnemonics( true, c );
|
||||
}
|
||||
|
||||
private static void showMnemonics( boolean show, Component c ) {
|
||||
if( show == showMnemonics )
|
||||
return;
|
||||
|
||||
showMnemonics = show;
|
||||
|
||||
// check whether it is necessary to repaint
|
||||
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )
|
||||
return;
|
||||
|
||||
if( show ) {
|
||||
// get root pane
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
if( rootPane == null )
|
||||
return;
|
||||
|
||||
// get window
|
||||
Window window = SwingUtilities.getWindowAncestor( rootPane );
|
||||
if( window == null )
|
||||
return;
|
||||
|
||||
// repaint components with mnemonics in focused window
|
||||
repaintMnemonics( window );
|
||||
|
||||
lastShowMnemonicWindow = new WeakReference<>( window );
|
||||
} else if( lastShowMnemonicWindow != null ) {
|
||||
Window window = lastShowMnemonicWindow.get();
|
||||
if( window != null )
|
||||
repaintMnemonics( window );
|
||||
|
||||
lastShowMnemonicWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void repaintMnemonics( Container container ) {
|
||||
for( Component c : container.getComponents() ) {
|
||||
if( !c.isVisible() )
|
||||
continue;
|
||||
|
||||
if( hasMnemonic( c ) )
|
||||
c.repaint();
|
||||
|
||||
if( c instanceof Container )
|
||||
repaintMnemonics( (Container) c );
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMnemonic( Component c ) {
|
||||
if( c instanceof JLabel && ((JLabel)c).getDisplayedMnemonicIndex() >= 0 )
|
||||
return true;
|
||||
|
||||
if( c instanceof AbstractButton && ((AbstractButton)c).getDisplayedMnemonicIndex() >= 0 )
|
||||
return true;
|
||||
|
||||
if( c instanceof JTabbedPane ) {
|
||||
JTabbedPane tabPane = (JTabbedPane) c;
|
||||
int tabCount = tabPane.getTabCount();
|
||||
for( int i = 0; i < tabCount; i++ ) {
|
||||
if( tabPane.getDisplayedMnemonicIndexAt( i ) >= 0 )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
public static void hideMnemonics() {
|
||||
MnemonicHandler.showMnemonics( false, null );
|
||||
}
|
||||
|
||||
//---- class ActiveFont ---------------------------------------------------
|
||||
@@ -620,4 +571,15 @@ public abstract class FlatLaf
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class ImageIconUIResource ------------------------------------------
|
||||
|
||||
private static class ImageIconUIResource
|
||||
extends ImageIcon
|
||||
implements UIResource
|
||||
{
|
||||
ImageIconUIResource( Image image ) {
|
||||
super( image );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class FlatLightLaf
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Flat Light";
|
||||
return "FlatLaf Light";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Flat Light Look and Feel";
|
||||
return "FlatLaf Light Look and Feel";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A Flat LaF that is able to load UI defaults from properties passed to the constructor.
|
||||
* <p>
|
||||
* Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}.
|
||||
* Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark},
|
||||
* {@code intellij} or {@code darcula}.
|
||||
* <p>
|
||||
* The properties are applied after loading the base theme and may overwrite base properties.
|
||||
* All features of FlatLaf properties files are available.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPropertiesLaf
|
||||
extends FlatLaf
|
||||
{
|
||||
private final String name;
|
||||
private final String baseTheme;
|
||||
private final boolean dark;
|
||||
private final Properties properties;
|
||||
|
||||
public FlatPropertiesLaf( String name, File propertiesFile )
|
||||
throws IOException
|
||||
{
|
||||
this( name, new FileInputStream( propertiesFile ) );
|
||||
}
|
||||
|
||||
public FlatPropertiesLaf( String name, InputStream in )
|
||||
throws IOException
|
||||
{
|
||||
this( name, loadProperties( in ) );
|
||||
}
|
||||
|
||||
private static Properties loadProperties( InputStream in )
|
||||
throws IOException
|
||||
{
|
||||
Properties properties = new Properties();
|
||||
try( InputStream in2 = in ) {
|
||||
properties.load( in2 );
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
public FlatPropertiesLaf( String name, Properties properties ) {
|
||||
this.name = name;
|
||||
this.properties = properties;
|
||||
|
||||
baseTheme = properties.getProperty( "@baseTheme", "light" );
|
||||
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDark() {
|
||||
return dark;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
lafClasses.add( FlatLaf.class );
|
||||
switch( baseTheme.toLowerCase() ) {
|
||||
default:
|
||||
case "light":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
break;
|
||||
|
||||
case "dark":
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
break;
|
||||
|
||||
case "intellij":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
lafClasses.add( FlatIntelliJLaf.class );
|
||||
break;
|
||||
|
||||
case "darcula":
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
lafClasses.add( FlatDarculaLaf.class );
|
||||
break;
|
||||
}
|
||||
return lafClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties getAdditionalDefaults() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class IntelliJTheme
|
||||
* Using a buffered input stream is not necessary.
|
||||
*/
|
||||
public static FlatLaf createLaf( InputStream in )
|
||||
throws IOException, ParseException
|
||||
throws IOException
|
||||
{
|
||||
return createLaf( new IntelliJTheme( in ) );
|
||||
}
|
||||
@@ -106,11 +106,13 @@ public class IntelliJTheme
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public IntelliJTheme( InputStream in )
|
||||
throws IOException, ParseException
|
||||
throws IOException
|
||||
{
|
||||
Map<String, Object> json;
|
||||
try( Reader reader = new InputStreamReader( in, StandardCharsets.UTF_8 ) ) {
|
||||
json = (Map<String, Object>) Json.parse( reader );
|
||||
} catch( ParseException ex ) {
|
||||
throw new IOException( ex.getMessage(), ex );
|
||||
}
|
||||
|
||||
name = (String) json.get( "name" );
|
||||
@@ -132,6 +134,8 @@ public class IntelliJTheme
|
||||
defaults.put( "Button.paintShadow", true );
|
||||
defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
|
||||
|
||||
Map<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
|
||||
|
||||
loadNamedColors( defaults );
|
||||
|
||||
// convert Json "ui" structure to UI defaults
|
||||
@@ -183,6 +187,42 @@ public class IntelliJTheme
|
||||
if( !uiKeys.contains( "Spinner.background" ) )
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
}
|
||||
|
||||
// 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" ) );
|
||||
|
||||
// limit tree row height
|
||||
int rowHeight = defaults.getInt( "Tree.rowHeight" );
|
||||
if( rowHeight > 22 )
|
||||
defaults.put( "Tree.rowHeight", 22 );
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
defaults.putAll( themeSpecificDefaults );
|
||||
}
|
||||
|
||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
// search for theme specific UI defaults keys
|
||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && ((String)key).startsWith( "[" ) )
|
||||
themeSpecificKeys.add( (String) key );
|
||||
}
|
||||
|
||||
// remove theme specific UI defaults and remember only those for current theme
|
||||
Map<Object, Object> themeSpecificDefaults = new HashMap<>();
|
||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
||||
for( String key : themeSpecificKeys ) {
|
||||
Object value = defaults.remove( key );
|
||||
if( key.startsWith( currentThemePrefix ) )
|
||||
themeSpecificDefaults.put( key.substring( currentThemePrefix.length() ), value );
|
||||
}
|
||||
|
||||
return themeSpecificDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,7 +240,7 @@ public class IntelliJTheme
|
||||
if( color != null ) {
|
||||
String key = e.getKey();
|
||||
namedColors.put( key, color );
|
||||
defaults.put( "ColorPalette." + e.getKey(), color );
|
||||
defaults.put( "ColorPalette." + key, color );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,6 +256,11 @@ public class IntelliJTheme
|
||||
} else {
|
||||
uiKeys.add( key );
|
||||
|
||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
||||
boolean isMaterialUILite = author.equals( "Mallowigi" );
|
||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
||||
return; // ignore
|
||||
|
||||
// map keys
|
||||
key = uiKeyMapping.getOrDefault( key, key );
|
||||
if( key.isEmpty() )
|
||||
@@ -270,7 +315,7 @@ public class IntelliJTheme
|
||||
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
||||
// because it is mapped from ComboBox.ArrowButton.background)
|
||||
String km = uiKeyInverseMapping.getOrDefault( k, (String) k );
|
||||
if( km.endsWith( tail ) && !noWildcardReplace.contains( k ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
||||
if( km.endsWith( tail ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
||||
defaults.put( k, uiValue );
|
||||
}
|
||||
}
|
||||
@@ -412,7 +457,6 @@ public class IntelliJTheme
|
||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
private static Set<String> noWildcardReplace = new HashSet<>();
|
||||
|
||||
static {
|
||||
// ComboBox
|
||||
@@ -423,6 +467,12 @@ public class IntelliJTheme
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
||||
|
||||
// Component
|
||||
uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" );
|
||||
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
||||
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
||||
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
||||
|
||||
// Link
|
||||
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
||||
|
||||
@@ -470,16 +520,6 @@ public class IntelliJTheme
|
||||
Map.Entry<String, String>[] entries = checkboxDuplicateColors.entrySet().toArray( new Map.Entry[checkboxDuplicateColors.size()] );
|
||||
for( Map.Entry<String, String> e : entries )
|
||||
checkboxDuplicateColors.put( e.getValue(), e.getKey() );
|
||||
|
||||
// because FlatLaf uses Button.background and Button.borderColor,
|
||||
// but IDEA uses Button.startBackground and Button.startBorderColor,
|
||||
// our default button background and border colors may be replaced by
|
||||
// wildcard *.background and *.borderColor colors
|
||||
noWildcardReplace.add( "Button.background" );
|
||||
noWildcardReplace.add( "Button.borderColor" );
|
||||
noWildcardReplace.add( "Button.default.background" );
|
||||
noWildcardReplace.add( "Button.default.borderColor" );
|
||||
noWildcardReplace.add( "ToggleButton.background" );
|
||||
}
|
||||
|
||||
//---- class ThemeLaf -----------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.KeyEventPostProcessor;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* Show/hide mnemonics.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class MnemonicHandler
|
||||
implements KeyEventPostProcessor, ChangeListener
|
||||
{
|
||||
private static boolean showMnemonics;
|
||||
private static WeakReference<Window> lastShowMnemonicWindow;
|
||||
private static WindowListener windowListener;
|
||||
|
||||
static boolean isShowMnemonics() {
|
||||
return showMnemonics || !UIManager.getBoolean( "Component.hideMnemonics" );
|
||||
}
|
||||
|
||||
void install() {
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( this );
|
||||
MenuSelectionManager.defaultManager().addChangeListener( this );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor( this );
|
||||
MenuSelectionManager.defaultManager().removeChangeListener( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postProcessKeyEvent( KeyEvent e ) {
|
||||
int keyCode = e.getKeyCode();
|
||||
if( SystemInfo.IS_MAC ) {
|
||||
// Ctrl+Alt keys must be pressed on Mac
|
||||
if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( shouldShowMnemonics( e ) && e.isControlDown() && e.isAltDown(), e.getComponent() );
|
||||
} else {
|
||||
// Alt key must be pressed on Windows and Linux
|
||||
if( SystemInfo.IS_WINDOWS )
|
||||
return processKeyEventOnWindows( e );
|
||||
|
||||
if( keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean shouldShowMnemonics( KeyEvent e ) {
|
||||
return e.getID() == KeyEvent.KEY_PRESSED ||
|
||||
MenuSelectionManager.defaultManager().getSelectedPath().length > 0;
|
||||
}
|
||||
|
||||
private static int altPressedEventCount;
|
||||
private static boolean selectMenuOnAltReleased;
|
||||
|
||||
/**
|
||||
* Special Alt key behavior on Windows.
|
||||
*
|
||||
* Press-and-release Alt key selects first menu (if available) and moves focus
|
||||
* temporary to menu bar. If menu bar has focus (some menu is selected),
|
||||
* pressing Alt key unselects menu and moves focus back to permanent focus owner.
|
||||
*/
|
||||
private boolean processKeyEventOnWindows( KeyEvent e ) {
|
||||
if( e.getKeyCode() != KeyEvent.VK_ALT ) {
|
||||
selectMenuOnAltReleased = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( e.getID() == KeyEvent.KEY_PRESSED ) {
|
||||
altPressedEventCount++;
|
||||
|
||||
if( altPressedEventCount == 1 && !e.isConsumed() ) {
|
||||
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||
selectMenuOnAltReleased = (menuSelectionManager.getSelectedPath().length == 0);
|
||||
|
||||
// if menu is selected when Alt key is pressed then clear menu selection
|
||||
if( !selectMenuOnAltReleased )
|
||||
menuSelectionManager.clearSelectedPath();
|
||||
}
|
||||
|
||||
// show mnemonics
|
||||
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||
|
||||
// avoid that the system menu of the window gets focus
|
||||
e.consume();
|
||||
return true;
|
||||
|
||||
} else if( e.getID() == KeyEvent.KEY_RELEASED ) {
|
||||
altPressedEventCount = 0;
|
||||
|
||||
boolean mnemonicsShown = false;
|
||||
if( selectMenuOnAltReleased && !e.isConsumed() ) {
|
||||
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||
if( menuSelectionManager.getSelectedPath().length == 0 ) {
|
||||
// get menu bar and first menu
|
||||
Component c = e.getComponent();
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
Window window = (rootPane != null) ? SwingUtilities.getWindowAncestor( rootPane ) : null;
|
||||
JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null;
|
||||
if( menuBar == null && window instanceof JFrame )
|
||||
menuBar = ((JFrame)window).getJMenuBar();
|
||||
JMenu firstMenu = (menuBar != null) ? menuBar.getMenu( 0 ) : null;
|
||||
|
||||
// select first menu and show mnemonics
|
||||
if( firstMenu != null ) {
|
||||
menuSelectionManager.setSelectedPath( new MenuElement[] { menuBar, firstMenu } );
|
||||
showMnemonics( true, c );
|
||||
mnemonicsShown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
selectMenuOnAltReleased = false;
|
||||
|
||||
// hide mnemonics
|
||||
if( !mnemonicsShown )
|
||||
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
if( selectedPath.length == 0 && altPressedEventCount == 0 ) {
|
||||
// hide mnemonics when menu selection was canceled
|
||||
showMnemonics( false, null );
|
||||
}
|
||||
}
|
||||
|
||||
static void showMnemonics( boolean show, Component c ) {
|
||||
if( show == showMnemonics )
|
||||
return;
|
||||
|
||||
showMnemonics = show;
|
||||
|
||||
// check whether it is necessary to repaint
|
||||
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )
|
||||
return;
|
||||
|
||||
if( show ) {
|
||||
// get root pane
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
if( rootPane == null )
|
||||
return;
|
||||
|
||||
// get window
|
||||
Window window = SwingUtilities.getWindowAncestor( rootPane );
|
||||
if( window == null )
|
||||
return;
|
||||
|
||||
// repaint components with mnemonics in focused window
|
||||
repaintMnemonics( window );
|
||||
|
||||
// hide mnemonics if window is deactivated (e.g. Alt+Tab to another window)
|
||||
windowListener = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowDeactivated( WindowEvent e ) {
|
||||
altPressedEventCount = 0;
|
||||
selectMenuOnAltReleased = false;
|
||||
|
||||
// use invokeLater() to avoid that the listener is removed
|
||||
// while the listener queue is iterated to fire this event
|
||||
EventQueue.invokeLater( () -> {
|
||||
showMnemonics( false, null );
|
||||
} );
|
||||
}
|
||||
};
|
||||
window.addWindowListener( windowListener );
|
||||
|
||||
lastShowMnemonicWindow = new WeakReference<>( window );
|
||||
} else if( lastShowMnemonicWindow != null ) {
|
||||
Window window = lastShowMnemonicWindow.get();
|
||||
if( window != null ) {
|
||||
repaintMnemonics( window );
|
||||
|
||||
if( windowListener != null ) {
|
||||
window.removeWindowListener( windowListener );
|
||||
windowListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
lastShowMnemonicWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void repaintMnemonics( Container container ) {
|
||||
for( Component c : container.getComponents() ) {
|
||||
if( !c.isVisible() )
|
||||
continue;
|
||||
|
||||
if( hasMnemonic( c ) )
|
||||
c.repaint();
|
||||
|
||||
if( c instanceof Container )
|
||||
repaintMnemonics( (Container) c );
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMnemonic( Component c ) {
|
||||
if( c instanceof JLabel && ((JLabel)c).getDisplayedMnemonicIndex() >= 0 )
|
||||
return true;
|
||||
|
||||
if( c instanceof AbstractButton && ((AbstractButton)c).getDisplayedMnemonicIndex() >= 0 )
|
||||
return true;
|
||||
|
||||
if( c instanceof JTabbedPane ) {
|
||||
JTabbedPane tabPane = (JTabbedPane) c;
|
||||
int tabCount = tabPane.getTabCount();
|
||||
for( int i = 0; i < tabCount; i++ ) {
|
||||
if( tabPane.getDisplayedMnemonicIndexAt( i ) >= 0 )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,9 @@ import javax.swing.plaf.InsetsUIResource;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
@@ -62,14 +64,12 @@ class UIDefaultsLoader
|
||||
private static final String TYPE_PREFIX = "{";
|
||||
private static final String TYPE_PREFIX_END = "}";
|
||||
private static final String VARIABLE_PREFIX = "@";
|
||||
@Deprecated
|
||||
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
|
||||
private static final String PROPERTY_PREFIX = "$";
|
||||
private static final String OPTIONAL_PREFIX = "?";
|
||||
private static final String GLOBAL_PREFIX = "*.";
|
||||
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, UIDefaults defaults )
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
// determine classes in class hierarchy in reverse order
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
@@ -80,11 +80,11 @@ class UIDefaultsLoader
|
||||
lafClasses.add( 0, lafClass );
|
||||
}
|
||||
|
||||
loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, defaults );
|
||||
loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults );
|
||||
}
|
||||
|
||||
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, UIDefaults defaults )
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
try {
|
||||
// load core properties files
|
||||
@@ -121,14 +121,28 @@ class UIDefaultsLoader
|
||||
|
||||
// collect all platform specific keys (but do not modify properties)
|
||||
ArrayList<String> platformSpecificKeys = new ArrayList<>();
|
||||
for( Object key : properties.keySet() ) {
|
||||
if( ((String)key).startsWith( "[" ) )
|
||||
platformSpecificKeys.add( (String) key );
|
||||
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.IS_WINDOWS ? "[win]" :
|
||||
SystemInfo.IS_MAC ? "[mac]" :
|
||||
@@ -198,12 +212,6 @@ class UIDefaultsLoader
|
||||
else if( !value.startsWith( VARIABLE_PREFIX ) )
|
||||
return value;
|
||||
|
||||
// for compatibility
|
||||
if( value.startsWith( REF_PREFIX ) ) {
|
||||
FlatLaf.LOG.log( Level.WARNING, "FlatLaf: Usage of '@@' in .properties files is deprecated. Use '$' instead." );
|
||||
value = value.substring( REF_PREFIX.length() );
|
||||
}
|
||||
|
||||
boolean optional = false;
|
||||
if( value.startsWith( OPTIONAL_PREFIX ) ) {
|
||||
value = value.substring( OPTIONAL_PREFIX.length() );
|
||||
@@ -222,7 +230,7 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
private enum ValueType { UNKNOWN, STRING, CHARACTER, INTEGER, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR,
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS }
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER }
|
||||
|
||||
static Object parseValue( String key, String value ) {
|
||||
return parseValue( key, value, v -> v, Collections.emptyList() );
|
||||
@@ -289,6 +297,8 @@ class UIDefaultsLoader
|
||||
valueType = ValueType.CHARACTER;
|
||||
else if( key.endsWith( "UI" ) )
|
||||
valueType = ValueType.STRING;
|
||||
else if( key.endsWith( "grayFilter" ) )
|
||||
valueType = ValueType.GRAYFILTER;
|
||||
}
|
||||
|
||||
// parse value
|
||||
@@ -308,6 +318,7 @@ class UIDefaultsLoader
|
||||
case SCALEDDIMENSION:return parseScaledDimension( value );
|
||||
case INSTANCE: return parseInstance( value, addonClassLoaders );
|
||||
case CLASS: return parseClass( value, addonClassLoaders );
|
||||
case GRAYFILTER: return parseGrayFilter( value );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
// colors
|
||||
@@ -497,29 +508,42 @@ class UIDefaultsLoader
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
|
||||
switch( function ) {
|
||||
case "rgb": return parseColorRgbOrRgba( false, params );
|
||||
case "rgba": return parseColorRgbOrRgba( true, params );
|
||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver, reportError );
|
||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver, reportError );
|
||||
case "hsl": return parseColorHslOrHsla( false, params );
|
||||
case "hsla": return parseColorHslOrHsla( true, params );
|
||||
case "lighten": return parseColorLightenOrDarken( true, params, resolver, reportError );
|
||||
case "darken": return parseColorLightenOrDarken( false, params, resolver, reportError );
|
||||
case "lighten": return parseColorHSLIncreaseDecrease( 2, true, params, resolver, reportError );
|
||||
case "darken": return parseColorHSLIncreaseDecrease( 2, false, params, resolver, reportError );
|
||||
case "saturate": return parseColorHSLIncreaseDecrease( 1, true, params, resolver, reportError );
|
||||
case "desaturate": return parseColorHSLIncreaseDecrease( 1, false, params, resolver, reportError );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "unknown color function '" + value + "'" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
|
||||
* - red: an integer 0-255
|
||||
* - green: an integer 0-255
|
||||
* - blue: an integer 0-255
|
||||
* - alpha: an integer 0-255
|
||||
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha) or rgba(color,alpha)
|
||||
* - red: an integer 0-255 or a percentage 0-100%
|
||||
* - green: an integer 0-255 or a percentage 0-100%
|
||||
* - blue: an integer 0-255 or a percentage 0-100%
|
||||
* - alpha: an integer 0-255 or a percentage 0-100%
|
||||
*/
|
||||
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params ) {
|
||||
int red = parseInteger( params.get( 0 ), 0, 255 );
|
||||
int green = parseInteger( params.get( 1 ), 0, 255 );
|
||||
int blue = parseInteger( params.get( 2 ), 0, 255 );
|
||||
int alpha = hasAlpha ? parseInteger( params.get( 3 ), 0, 255 ) : 255;
|
||||
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params,
|
||||
Function<String, String> resolver, boolean reportError )
|
||||
{
|
||||
if( hasAlpha && params.size() == 2 ) {
|
||||
// syntax rgba(color,alpha), which allows adding alpha to any color
|
||||
String colorStr = params.get( 0 );
|
||||
int alpha = parseInteger( params.get( 1 ), 0, 255, true );
|
||||
|
||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
return new ColorUIResource( new Color( ((alpha & 0xff) << 24) | (color.getRGB() & 0xffffff), true ) );
|
||||
}
|
||||
|
||||
int red = parseInteger( params.get( 0 ), 0, 255, true );
|
||||
int green = parseInteger( params.get( 1 ), 0, 255, true );
|
||||
int blue = parseInteger( params.get( 2 ), 0, 255, true );
|
||||
int alpha = hasAlpha ? parseInteger( params.get( 3 ), 0, 255, true ) : 255;
|
||||
|
||||
return hasAlpha
|
||||
? new ColorUIResource( new Color( red, green, blue, alpha ) )
|
||||
@@ -534,7 +558,7 @@ class UIDefaultsLoader
|
||||
* - alpha: a percentage 0-100%
|
||||
*/
|
||||
private static ColorUIResource parseColorHslOrHsla( boolean hasAlpha, List<String> params ) {
|
||||
int hue = parseInteger( params.get( 0 ), 0, 360 );
|
||||
int hue = parseInteger( params.get( 0 ), 0, 360, false );
|
||||
int saturation = parsePercentage( params.get( 1 ) );
|
||||
int lightness = parsePercentage( params.get( 2 ) );
|
||||
int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100;
|
||||
@@ -544,35 +568,33 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: lighten([color,]amount[,options]) or darken([color,]amount[,options])
|
||||
* Syntax: lighten(color,amount[,options]) or darken(color,amount[,options]) or
|
||||
* saturate(color,amount[,options]) or desaturate(color,amount[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - amount: percentage 0-100%
|
||||
* - options: [relative] [autoInverse] [lazy]
|
||||
* - options: [relative] [autoInverse] [lazy] [derived]
|
||||
*/
|
||||
private static Object parseColorLightenOrDarken( boolean lighten, List<String> params,
|
||||
Function<String, String> resolver, boolean reportError )
|
||||
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||
List<String> params, Function<String, String> resolver, boolean reportError )
|
||||
{
|
||||
boolean isDerived = params.get( 0 ).endsWith( "%" );
|
||||
String colorStr = isDerived ? null : params.get( 0 );
|
||||
int nextParam = isDerived ? 0 : 1;
|
||||
int amount = parsePercentage( params.get( nextParam++ ) );
|
||||
String colorStr = params.get( 0 );
|
||||
int amount = parsePercentage( params.get( 1 ) );
|
||||
boolean relative = false;
|
||||
boolean autoInverse = false;
|
||||
boolean lazy = false;
|
||||
boolean derived = false;
|
||||
|
||||
if( params.size() > nextParam ) {
|
||||
String options = params.get( nextParam++ );
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
relative = options.contains( "relative" );
|
||||
autoInverse = options.contains( "autoInverse" );
|
||||
lazy = options.contains( "lazy" );
|
||||
derived = options.contains( "derived" );
|
||||
}
|
||||
|
||||
ColorFunctions.ColorFunction function = lighten
|
||||
? new ColorFunctions.Lighten( amount, relative, autoInverse )
|
||||
: new ColorFunctions.Darken( amount, relative, autoInverse );
|
||||
|
||||
if( isDerived )
|
||||
return new DerivedColor( function );
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease(
|
||||
hslIndex, increase, amount, relative, autoInverse );
|
||||
|
||||
if( lazy ) {
|
||||
return (LazyValue) t -> {
|
||||
@@ -583,8 +605,27 @@ class UIDefaultsLoader
|
||||
};
|
||||
}
|
||||
|
||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
return new ColorUIResource( ColorFunctions.applyFunctions( color, function ) );
|
||||
// parse base color
|
||||
ColorUIResource baseColor = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
|
||||
// apply this function to base color
|
||||
Color newColor = ColorFunctions.applyFunctions( baseColor, function );
|
||||
|
||||
if( derived ) {
|
||||
ColorFunction[] functions;
|
||||
if( baseColor instanceof DerivedColor ) {
|
||||
// if the base color is also derived, join the color functions
|
||||
ColorFunction[] baseFunctions = ((DerivedColor)baseColor).getFunctions();
|
||||
functions = new ColorFunction[baseFunctions.length + 1];
|
||||
System.arraycopy( baseFunctions, 0, functions, 0, baseFunctions.length );
|
||||
functions[baseFunctions.length] = function;
|
||||
} else
|
||||
functions = new ColorFunction[] { function };
|
||||
|
||||
return new DerivedColor( newColor, functions );
|
||||
}
|
||||
|
||||
return new ColorUIResource( newColor );
|
||||
}
|
||||
|
||||
private static int parsePercentage( String value ) {
|
||||
@@ -609,7 +650,12 @@ class UIDefaultsLoader
|
||||
return value.charAt( 0 );
|
||||
}
|
||||
|
||||
private static Integer parseInteger( String value, int min, int max ) {
|
||||
private static Integer parseInteger( String value, int min, int max, boolean allowPercentage ) {
|
||||
if( allowPercentage && value.endsWith( "%" ) ) {
|
||||
int percent = parsePercentage( value );
|
||||
return (max * percent) / 100;
|
||||
}
|
||||
|
||||
Integer integer = parseInteger( value, true );
|
||||
if( integer.intValue() < min || integer.intValue() > max )
|
||||
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
||||
@@ -664,6 +710,21 @@ class UIDefaultsLoader
|
||||
};
|
||||
}
|
||||
|
||||
private static Object parseGrayFilter( String value ) {
|
||||
List<String> numbers = split( value, ',' );
|
||||
try {
|
||||
int brightness = Integer.parseInt( numbers.get( 0 ) );
|
||||
int contrast = Integer.parseInt( numbers.get( 1 ) );
|
||||
int alpha = Integer.parseInt( numbers.get( 2 ) );
|
||||
|
||||
return (LazyValue) t -> {
|
||||
return new GrayFilter( brightness, contrast, alpha );
|
||||
};
|
||||
} catch( NumberFormatException ex ) {
|
||||
throw new IllegalArgumentException( "invalid gray filter '" + value + "'" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split string and trim parts.
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,8 @@ import javax.swing.UIManager;
|
||||
*
|
||||
* @uiDefault MenuItemCheckBox.icon.checkmarkColor Color
|
||||
* @uiDefault MenuItemCheckBox.icon.disabledCheckmarkColor Color
|
||||
* @uiDefault Menu.selectionForeground Color
|
||||
* @uiDefault MenuItem.selectionForeground Color
|
||||
* @uiDefault MenuItem.selectionType String
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -39,7 +40,7 @@ public class FlatCheckBoxMenuItemIcon
|
||||
{
|
||||
protected final Color checkmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.checkmarkColor" );
|
||||
protected final Color disabledCheckmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.disabledCheckmarkColor" );
|
||||
protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
||||
protected final Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
||||
|
||||
public FlatCheckBoxMenuItemIcon() {
|
||||
super( 15, 15, null );
|
||||
@@ -67,9 +68,14 @@ public class FlatCheckBoxMenuItemIcon
|
||||
}
|
||||
|
||||
private Color getCheckmarkColor( Component c ) {
|
||||
if( c instanceof JMenuItem && ((JMenuItem)c).isArmed() )
|
||||
if( c instanceof JMenuItem && ((JMenuItem)c).isArmed() && !isUnderlineSelection() )
|
||||
return selectionForeground;
|
||||
|
||||
return c.isEnabled() ? checkmarkColor : disabledCheckmarkColor;
|
||||
}
|
||||
|
||||
private boolean isUnderlineSelection() {
|
||||
// not storing value of "MenuItem.selectionType" in class to allow changing at runtime
|
||||
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
* @uiDefault Menu.icon.arrowColor Color
|
||||
* @uiDefault Menu.icon.disabledArrowColor Color
|
||||
* @uiDefault Menu.selectionForeground Color
|
||||
* @uiDefault MenuItem.selectionType String
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -65,9 +66,14 @@ public class FlatMenuArrowIcon
|
||||
}
|
||||
|
||||
private Color getArrowColor( Component c ) {
|
||||
if( c instanceof JMenu && ((JMenu)c).isSelected() )
|
||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||
return selectionForeground;
|
||||
|
||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||
}
|
||||
|
||||
private boolean isUnderlineSelection() {
|
||||
// not storing value of "MenuItem.selectionType" in class to allow changing at runtime
|
||||
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicBorders;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
|
||||
/**
|
||||
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
||||
@@ -54,6 +56,12 @@ import javax.swing.text.JTextComponent;
|
||||
* @uiDefault Component.disabledBorderColor Color
|
||||
* @uiDefault Component.focusedBorderColor Color
|
||||
*
|
||||
* @uiDefault Component.error.borderColor Color
|
||||
* @uiDefault Component.error.focusedBorderColor Color
|
||||
* @uiDefault Component.warning.borderColor Color
|
||||
* @uiDefault Component.warning.focusedBorderColor Color
|
||||
* @uiDefault Component.custom.borderColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatBorder
|
||||
@@ -61,11 +69,18 @@ public class FlatBorder
|
||||
{
|
||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||
protected final float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
protected final Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||
protected final Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||
protected final Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
||||
|
||||
protected final Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
||||
protected final Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||
protected final Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||
protected final Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||
protected final Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
@@ -73,25 +88,53 @@ public class FlatBorder
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
boolean isCellEditor = isTableCellEditor( c );
|
||||
float focusWidth = isCellEditor ? 0 : getFocusWidth( c );
|
||||
float borderWidth = getBorderWidth( c );
|
||||
float arc = isCellEditor ? 0 : getArc( c );
|
||||
float focusWidth = isCellEditor ? 0 : scale( (float) getFocusWidth( c ) );
|
||||
float borderWidth = scale( (float) getBorderWidth( c ) );
|
||||
float arc = isCellEditor ? 0 : scale( (float) getArc( c ) );
|
||||
Color outlineColor = getOutlineColor( c );
|
||||
|
||||
if( isFocused( c ) ) {
|
||||
float innerFocusWidth = !(c instanceof JScrollPane) ? this.innerFocusWidth : 0;
|
||||
if( outlineColor != null || isFocused( c ) ) {
|
||||
float innerFocusWidth = !(c instanceof JScrollPane)
|
||||
? (outlineColor != null ? innerOutlineWidth : this.innerFocusWidth)
|
||||
: 0;
|
||||
|
||||
g2.setColor( getFocusColor( c ) );
|
||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height, focusWidth,
|
||||
getLineWidth( c ) + scale( innerFocusWidth ), arc );
|
||||
scale( (float) getLineWidth( c ) ) + scale( innerFocusWidth ), arc );
|
||||
}
|
||||
|
||||
g2.setPaint( getBorderColor( c ) );
|
||||
g2.setPaint( (outlineColor != null) ? outlineColor : getBorderColor( c ) );
|
||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected Color getOutlineColor( Component c ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return null;
|
||||
|
||||
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
||||
if( outline instanceof String ) {
|
||||
switch( (String) outline ) {
|
||||
case FlatClientProperties.OUTLINE_ERROR:
|
||||
return isFocused( c ) ? errorFocusedBorderColor : errorBorderColor;
|
||||
|
||||
case FlatClientProperties.OUTLINE_WARNING:
|
||||
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
||||
}
|
||||
} else if( outline instanceof Color ) {
|
||||
Color color = (Color) outline;
|
||||
// use color functions to compute color for unfocused state
|
||||
if( !isFocused( c ) && customBorderColor instanceof DerivedColor )
|
||||
color = ((DerivedColor)customBorderColor).derive( color );
|
||||
return color;
|
||||
} else if( outline instanceof Color[] && ((Color[])outline).length >= 2 )
|
||||
return ((Color[])outline)[isFocused( c ) ? 0 : 1];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Color getFocusColor( Component c ) {
|
||||
return focusColor;
|
||||
}
|
||||
@@ -153,7 +196,8 @@ public class FlatBorder
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
boolean isCellEditor = isTableCellEditor( c );
|
||||
float ow = (isCellEditor ? 0 : getFocusWidth( c )) + getLineWidth( c );
|
||||
float focusWidth = isCellEditor ? 0 : scale( (float) getFocusWidth( c ) );
|
||||
float ow = focusWidth + scale( (float) getLineWidth( c ) );
|
||||
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
insets.top = Math.round( scale( (float) insets.top ) + ow );
|
||||
@@ -163,19 +207,33 @@ public class FlatBorder
|
||||
return insets;
|
||||
}
|
||||
|
||||
protected float getFocusWidth( Component c ) {
|
||||
return scale( (float) focusWidth );
|
||||
/**
|
||||
* Returns the (unscaled) thickness of the outer focus border.
|
||||
*/
|
||||
protected int getFocusWidth( Component c ) {
|
||||
return focusWidth;
|
||||
}
|
||||
|
||||
protected float getLineWidth( Component c ) {
|
||||
return scale( 1f );
|
||||
/**
|
||||
* Returns the (unscaled) line thickness used to compute the border insets.
|
||||
* This may be different to {@link #getBorderWidth}.
|
||||
*/
|
||||
protected int getLineWidth( Component c ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected float getBorderWidth( Component c ) {
|
||||
/**
|
||||
* Returns the (unscaled) line thickness used to paint the border.
|
||||
* This may be different to {@link #getLineWidth}.
|
||||
*/
|
||||
protected int getBorderWidth( Component c ) {
|
||||
return getLineWidth( c );
|
||||
}
|
||||
|
||||
protected float getArc( Component c ) {
|
||||
/**
|
||||
* Returns the (unscaled) arc diameter of the border.
|
||||
*/
|
||||
protected int getArc( Component c ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.GradientPaint;
|
||||
@@ -124,17 +123,21 @@ public class FlatButtonBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getFocusWidth( Component c ) {
|
||||
return FlatToggleButtonUI.isTabButton( c ) ? 0 : super.getFocusWidth(c );
|
||||
protected int getFocusWidth( Component c ) {
|
||||
return FlatToggleButtonUI.isTabButton( c ) ? 0 : super.getFocusWidth( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBorderWidth( Component c ) {
|
||||
return FlatButtonUI.isDefaultButton( c ) ? scale( (float) defaultBorderWidth ) : super.getBorderWidth( c );
|
||||
protected int getBorderWidth( Component c ) {
|
||||
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : super.getBorderWidth( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getArc( Component c ) {
|
||||
return FlatButtonUI.isSquareButton( c ) ? 0 : scale( (float) arc );
|
||||
protected int getArc( Component c ) {
|
||||
switch( FlatButtonUI.getButtonType( c ) ) {
|
||||
case FlatButtonUI.TYPE_SQUARE: return 0;
|
||||
case FlatButtonUI.TYPE_ROUND_RECT: return Short.MAX_VALUE;
|
||||
default: return arc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicButtonListener;
|
||||
@@ -61,8 +60,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatButtonUI -->
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Button.arc int
|
||||
* @uiDefault Button.minimumWidth int
|
||||
* @uiDefault Button.iconTextGap int
|
||||
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
||||
@@ -92,8 +89,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatButtonUI
|
||||
extends BasicButtonUI
|
||||
{
|
||||
protected int focusWidth;
|
||||
protected int arc;
|
||||
protected int minimumWidth;
|
||||
protected int iconTextGap;
|
||||
|
||||
@@ -139,8 +134,6 @@ public class FlatButtonUI
|
||||
if( !defaults_initialized ) {
|
||||
String prefix = getPropertyPrefix();
|
||||
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
arc = UIManager.getInt( "Button.arc" );
|
||||
minimumWidth = UIManager.getInt( prefix + "minimumWidth" );
|
||||
iconTextGap = FlatUIUtils.getUIInt( prefix + "iconTextGap", 4 );
|
||||
|
||||
@@ -187,7 +180,7 @@ public class FlatButtonUI
|
||||
LookAndFeel.installProperty( b, "opaque", false );
|
||||
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
||||
|
||||
MigLayoutVisualPadding.install( b, getFocusWidth( b ) );
|
||||
MigLayoutVisualPadding.install( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,6 +208,10 @@ public class FlatButtonUI
|
||||
case MINIMUM_HEIGHT:
|
||||
b.revalidate();
|
||||
break;
|
||||
|
||||
case BUTTON_TYPE:
|
||||
b.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,8 +233,15 @@ public class FlatButtonUI
|
||||
(icon == null && text != null && ("...".equals( text ) || text.length() == 1));
|
||||
}
|
||||
|
||||
static boolean isSquareButton( Component c ) {
|
||||
return c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_SQUARE );
|
||||
// same indices as in parameters to clientPropertyChoice()
|
||||
static final int TYPE_OTHER = -1;
|
||||
static final int TYPE_SQUARE = 0;
|
||||
static final int TYPE_ROUND_RECT = 1;
|
||||
|
||||
static int getButtonType( Component c ) {
|
||||
return (c instanceof AbstractButton)
|
||||
? clientPropertyChoice( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_SQUARE, BUTTON_TYPE_ROUND_RECT )
|
||||
: TYPE_OTHER;
|
||||
}
|
||||
|
||||
static boolean isHelpButton( Component c ) {
|
||||
@@ -245,7 +249,8 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
static boolean isToolBarButton( Component c ) {
|
||||
return c.getParent() instanceof JToolBar;
|
||||
return c.getParent() instanceof JToolBar ||
|
||||
(c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -272,11 +277,10 @@ public class FlatButtonUI
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
Border border = c.getBorder();
|
||||
boolean isToolBarButton = isToolBarButton( c );
|
||||
float focusWidth = (border instanceof FlatBorder && !isToolBarButton) ? scale( (float) getFocusWidth( c ) ) : 0;
|
||||
float arc = ((border instanceof FlatButtonBorder && !isSquareButton( c )) || isToolBarButton)
|
||||
? scale( (float) this.arc ) : 0;
|
||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
||||
float arc = FlatUIUtils.getBorderArc( c );
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
|
||||
int x = 0;
|
||||
@@ -401,7 +405,7 @@ public class FlatButtonUI
|
||||
return new Dimension( helpButtonIcon.getIconWidth(), helpButtonIcon.getIconHeight() );
|
||||
|
||||
Dimension prefSize = super.getPreferredSize( c );
|
||||
if ( prefSize == null )
|
||||
if( prefSize == null )
|
||||
return null;
|
||||
|
||||
// make button square if it is a icon-only button
|
||||
@@ -409,15 +413,11 @@ public class FlatButtonUI
|
||||
if( isIconOnlyButton( c ) )
|
||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||
else if( !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
||||
int focusWidth = getFocusWidth( c );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) + (focusWidth * 2) ) );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) + (focusWidth * 2) ) );
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + Math.round( focusWidth * 2 ) );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + Math.round( focusWidth * 2 ) );
|
||||
}
|
||||
|
||||
return prefSize;
|
||||
}
|
||||
|
||||
protected int getFocusWidth( JComponent c ) {
|
||||
return focusWidth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||
|
||||
@@ -30,29 +29,34 @@ import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||
*
|
||||
* <!-- BasicCheckBoxMenuItemUI -->
|
||||
*
|
||||
* @uiDefault CheckBoxMenuItem.font Font
|
||||
* @uiDefault CheckBoxMenuItem.background Color
|
||||
* @uiDefault CheckBoxMenuItem.foreground Color
|
||||
* @uiDefault CheckBoxMenuItem.disabledForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.selectionBackground Color
|
||||
* @uiDefault CheckBoxMenuItem.selectionForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.acceleratorForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault CheckBoxMenuItem.border Border
|
||||
* @uiDefault CheckBoxMenuItem.borderPainted boolean
|
||||
* @uiDefault CheckBoxMenuItem.margin Insets
|
||||
* @uiDefault CheckBoxMenuItem.arrowIcon Icon
|
||||
* @uiDefault CheckBoxMenuItem.checkIcon Icon
|
||||
* @uiDefault CheckBoxMenuItem.opaque boolean
|
||||
* @uiDefault CheckBoxMenuItem.evenHeight boolean
|
||||
* @uiDefault CheckBoxMenuItem.font Font
|
||||
* @uiDefault CheckBoxMenuItem.background Color
|
||||
* @uiDefault CheckBoxMenuItem.foreground Color
|
||||
* @uiDefault CheckBoxMenuItem.disabledForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.selectionBackground Color
|
||||
* @uiDefault CheckBoxMenuItem.selectionForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.acceleratorForeground Color
|
||||
* @uiDefault CheckBoxMenuItem.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault CheckBoxMenuItem.border Border
|
||||
* @uiDefault CheckBoxMenuItem.borderPainted boolean
|
||||
* @uiDefault CheckBoxMenuItem.margin Insets
|
||||
* @uiDefault CheckBoxMenuItem.arrowIcon Icon
|
||||
* @uiDefault CheckBoxMenuItem.checkIcon Icon
|
||||
* @uiDefault CheckBoxMenuItem.opaque boolean
|
||||
*
|
||||
* <!-- FlatCheckBoxMenuItemUI -->
|
||||
*
|
||||
* @uiDefault MenuItem.iconTextGap int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatCheckBoxMenuItemUI
|
||||
extends BasicCheckBoxMenuItemUI
|
||||
{
|
||||
private FlatMenuItemRenderer renderer;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatCheckBoxMenuItemUI();
|
||||
}
|
||||
@@ -61,25 +65,30 @@ public class FlatCheckBoxMenuItemUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
// scale
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
}
|
||||
LookAndFeel.installProperty( menuItem, "iconTextGap", FlatUIUtils.getUIInt( "MenuItem.iconTextGap", 4 ) );
|
||||
|
||||
/**
|
||||
* Scale defaultTextIconGap again if iconTextGap property has changed.
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener( c );
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
if( e.getPropertyName() == "iconTextGap" )
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
renderer = createRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
renderer = null;
|
||||
}
|
||||
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||
return renderer.getPreferredMenuItemSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
renderer.paintMenuItem( g, selectionBackground, selectionForeground, disabledForeground,
|
||||
acceleratorForeground, acceleratorSelectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatComboBoxUI -->
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.arc int
|
||||
* @uiDefault Component.arrowType String triangle (default) or chevron
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault Component.borderColor Color
|
||||
@@ -96,8 +94,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatComboBoxUI
|
||||
extends BasicComboBoxUI
|
||||
{
|
||||
protected int focusWidth;
|
||||
protected int arc;
|
||||
protected String arrowType;
|
||||
protected boolean isIntelliJTheme;
|
||||
protected Color borderColor;
|
||||
@@ -150,8 +146,6 @@ public class FlatComboBoxUI
|
||||
|
||||
LookAndFeel.installProperty( comboBox, "opaque", false );
|
||||
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
arc = UIManager.getInt( "Component.arc" );
|
||||
arrowType = UIManager.getString( "Component.arrowType" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
borderColor = UIManager.getColor( "Component.borderColor" );
|
||||
@@ -170,7 +164,7 @@ public class FlatComboBoxUI
|
||||
// scale
|
||||
padding = UIScale.scale( padding );
|
||||
|
||||
MigLayoutVisualPadding.install( comboBox, focusWidth );
|
||||
MigLayoutVisualPadding.install( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -249,6 +243,8 @@ public class FlatComboBoxUI
|
||||
editor.applyComponentOrientation( o );
|
||||
} else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) )
|
||||
editor.repaint();
|
||||
else if( FlatClientProperties.COMPONENT_ROUND_RECT.equals( propertyName ) )
|
||||
comboBox.repaint();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -318,8 +314,11 @@ public class FlatComboBoxUI
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
float arc = FlatUIUtils.getBorderArc( c );
|
||||
|
||||
// fill background if opaque to avoid garbage if user sets opaque to true
|
||||
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
|
||||
if( c.isOpaque() && (focusWidth > 0 || arc > 0) )
|
||||
FlatUIUtils.paintParentBackground( g, c );
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
@@ -327,8 +326,6 @@ public class FlatComboBoxUI
|
||||
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
|
||||
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
|
||||
int arrowX = arrowButton.getX();
|
||||
int arrowWidth = arrowButton.getWidth();
|
||||
boolean enabled = comboBox.isEnabled();
|
||||
@@ -394,8 +391,7 @@ public class FlatComboBoxUI
|
||||
|
||||
@Override
|
||||
public void paintCurrentValueBackground( Graphics g, Rectangle bounds, boolean hasFocus ) {
|
||||
g.setColor( comboBox.isEnabled() ? comboBox.getBackground() : getDisabledBackground( comboBox ) );
|
||||
g.fillRect( bounds.x, bounds.y, bounds.width, bounds.height );
|
||||
// not necessary because already painted in update()
|
||||
}
|
||||
|
||||
private Color getDisabledBackground( JComponent c ) {
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.RadialGradientPaint;
|
||||
import java.awt.image.BufferedImage;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Paints a drop shadow border around the component.
|
||||
* Supports 1-sided, 2-side, 3-sided or 4-sided drop shadows.
|
||||
* <p>
|
||||
* The shadow insets allow specifying drop shadow thickness for each side.
|
||||
* A zero or negative value hides the drop shadow on that side.
|
||||
* A negative value can be used to indent the drop shadow on corners.
|
||||
* E.g. -4 on left indents drop shadow at top-left and bottom-left corners by 4 pixels.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatDropShadowBorder
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
private final Color shadowColor;
|
||||
private final Insets shadowInsets;
|
||||
private final float shadowOpacity;
|
||||
|
||||
private final int shadowSize;
|
||||
private Image shadowImage;
|
||||
private Color lastShadowColor;
|
||||
private double lastSystemScaleFactor;
|
||||
private float lastUserScaleFactor;
|
||||
|
||||
public FlatDropShadowBorder() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
public FlatDropShadowBorder( Color shadowColor ) {
|
||||
this( shadowColor, 4, 0.5f );
|
||||
}
|
||||
|
||||
public FlatDropShadowBorder( Color shadowColor, int shadowSize, float shadowOpacity ) {
|
||||
this( shadowColor, new Insets( -shadowSize, -shadowSize, shadowSize, shadowSize ), shadowOpacity );
|
||||
}
|
||||
|
||||
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
||||
super( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
||||
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
||||
this.shadowColor = shadowColor;
|
||||
this.shadowInsets = shadowInsets;
|
||||
this.shadowOpacity = shadowOpacity;
|
||||
|
||||
shadowSize = Math.max(
|
||||
Math.max( shadowInsets.left, shadowInsets.right ),
|
||||
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( shadowSize <= 0 )
|
||||
return;
|
||||
|
||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, width, height, this::paintImpl );
|
||||
}
|
||||
|
||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
Color shadowColor = (this.shadowColor != null) ? this.shadowColor : g.getColor();
|
||||
int shadowSize = scale( this.shadowSize, scaleFactor );
|
||||
|
||||
// create and cache shadow image
|
||||
float userScaleFactor = UIScale.getUserScaleFactor();
|
||||
if( shadowImage == null ||
|
||||
!shadowColor.equals( lastShadowColor ) ||
|
||||
lastSystemScaleFactor != scaleFactor ||
|
||||
lastUserScaleFactor != userScaleFactor )
|
||||
{
|
||||
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
||||
(float) (scaleFactor * userScaleFactor) );
|
||||
lastShadowColor = shadowColor;
|
||||
lastSystemScaleFactor = scaleFactor;
|
||||
lastUserScaleFactor = userScaleFactor;
|
||||
}
|
||||
|
||||
/*debug
|
||||
int m = shadowImage.getWidth( null );
|
||||
Color oldColor = g.getColor();
|
||||
g.setColor( Color.lightGray );
|
||||
g.drawRect( x - m - 1, y - m - 1, m + 1, m + 1 );
|
||||
g.setColor( Color.white );
|
||||
g.fillRect( x - m, y - m, m, m );
|
||||
g.drawImage( shadowImage, x - m, y - m, null );
|
||||
g.setColor( oldColor );
|
||||
debug*/
|
||||
|
||||
int left = scale( shadowInsets.left, scaleFactor );
|
||||
int right = scale( shadowInsets.right, scaleFactor );
|
||||
int top = scale( shadowInsets.top, scaleFactor );
|
||||
int bottom = scale( shadowInsets.bottom, scaleFactor );
|
||||
|
||||
// shadow outer coordinates
|
||||
int x1o = x - Math.min( left, 0 );
|
||||
int y1o = y - Math.min( top, 0 );
|
||||
int x2o = x + width + Math.min( right, 0 );
|
||||
int y2o = y + height + Math.min( bottom, 0 );
|
||||
|
||||
// shadow inner coordinates
|
||||
int x1i = x1o + shadowSize;
|
||||
int y1i = y1o + shadowSize;
|
||||
int x2i = x2o - shadowSize;
|
||||
int y2i = y2o - shadowSize;
|
||||
|
||||
int wh = (shadowSize * 2) - 1;
|
||||
int center = shadowSize - 1;
|
||||
|
||||
// left-top edge
|
||||
if( left > 0 || top > 0 ) {
|
||||
g.drawImage( shadowImage, x1o, y1o, x1i, y1i,
|
||||
0, 0, center, center, null );
|
||||
}
|
||||
|
||||
// top shadow
|
||||
if( top > 0 ) {
|
||||
g.drawImage( shadowImage, x1i, y1o, x2i, y1i,
|
||||
center, 0, center + 1, center, null );
|
||||
}
|
||||
|
||||
// right-top edge
|
||||
if( right > 0 || top > 0 ) {
|
||||
g.drawImage( shadowImage, x2i, y1o, x2o, y1i,
|
||||
center, 0, wh, center, null );
|
||||
}
|
||||
|
||||
// left shadow
|
||||
if( left > 0 ) {
|
||||
g.drawImage( shadowImage, x1o, y1i, x1i, y2i,
|
||||
0, center, center, center + 1, null );
|
||||
}
|
||||
|
||||
// right shadow
|
||||
if( right > 0 ) {
|
||||
g.drawImage( shadowImage, x2i, y1i, x2o, y2i,
|
||||
center, center, wh, center + 1, null );
|
||||
}
|
||||
|
||||
// left-bottom edge
|
||||
if( left > 0 || bottom > 0 ) {
|
||||
g.drawImage( shadowImage, x1o, y2i, x1i, y2o,
|
||||
0, center, center, wh, null );
|
||||
}
|
||||
|
||||
// bottom shadow
|
||||
if( bottom > 0 ) {
|
||||
g.drawImage( shadowImage, x1i, y2i, x2i, y2o,
|
||||
center, center, center + 1, wh, null );
|
||||
}
|
||||
|
||||
// right-bottom edge
|
||||
if( right > 0 || bottom > 0 ) {
|
||||
g.drawImage( shadowImage, x2i, y2i, x2o, y2o,
|
||||
center, center, wh, wh, null );
|
||||
}
|
||||
}
|
||||
|
||||
private int scale( int value, double scaleFactor ) {
|
||||
return (int) Math.ceil( UIScale.scale( value ) * scaleFactor );
|
||||
}
|
||||
|
||||
private static BufferedImage createShadowImage( Color shadowColor, int shadowSize,
|
||||
float shadowOpacity, float scaleFactor )
|
||||
{
|
||||
int shadowRGB = shadowColor.getRGB() & 0xffffff;
|
||||
int shadowAlpha = (int) (255 * shadowOpacity);
|
||||
Color startColor = new Color( shadowRGB | ((shadowAlpha & 0xff) << 24), true );
|
||||
Color midColor = new Color( shadowRGB | (((shadowAlpha / 2) & 0xff) << 24), true );
|
||||
Color endColor = new Color( shadowRGB, true );
|
||||
|
||||
/*debug
|
||||
startColor = Color.red;
|
||||
midColor = Color.green;
|
||||
endColor = Color.blue;
|
||||
debug*/
|
||||
|
||||
int wh = (shadowSize * 2) - 1;
|
||||
int center = shadowSize - 1;
|
||||
|
||||
RadialGradientPaint p = new RadialGradientPaint( center, center,
|
||||
shadowSize - (0.75f * scaleFactor),
|
||||
new float[] { 0, 0.35f, 1 },
|
||||
new Color[] { startColor, midColor, endColor } );
|
||||
|
||||
BufferedImage image = new BufferedImage( wh, wh, BufferedImage.TYPE_INT_ARGB );
|
||||
|
||||
Graphics2D g = image.createGraphics();
|
||||
try {
|
||||
g.setPaint( p );
|
||||
g.fillRect( 0, 0, wh, wh );
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -85,20 +85,20 @@ public class FlatEditorPaneUI
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getPreferredSize( c ) );
|
||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getMinimumSize( c ) );
|
||||
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size ) {
|
||||
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
|
||||
// Assume that text area is in a scroll pane (that displays the border)
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
minimumWidth = FlatUIUtils.minimumWidth( c, minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,27 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.filechooser.FileView;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -86,6 +102,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault FileChooser.folderNameLabelText String
|
||||
* @uiDefault FileChooser.filesOfTypeLabelMnemonic String
|
||||
* @uiDefault FileChooser.filesOfTypeLabelText String
|
||||
*
|
||||
* @uiDefault FileChooser.upFolderToolTipText String
|
||||
* @uiDefault FileChooser.upFolderAccessibleName String
|
||||
* @uiDefault FileChooser.homeFolderToolTipText String
|
||||
@@ -97,11 +114,27 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault FileChooser.detailsViewButtonToolTipText String
|
||||
* @uiDefault FileChooser.detailsViewButtonAccessibleName String
|
||||
*
|
||||
* <!-- FilePane -->
|
||||
*
|
||||
* @uiDefault FileChooser.fileNameHeaderText String
|
||||
* @uiDefault FileChooser.fileSizeHeaderText String
|
||||
* @uiDefault FileChooser.fileTypeHeaderText String
|
||||
* @uiDefault FileChooser.fileDateHeaderText String
|
||||
* @uiDefault FileChooser.fileAttrHeaderText String
|
||||
*
|
||||
* @uiDefault FileChooser.viewMenuLabelText String
|
||||
* @uiDefault FileChooser.refreshActionLabelText String
|
||||
* @uiDefault FileChooser.newFolderActionLabelText String
|
||||
* @uiDefault FileChooser.listViewActionLabelText String
|
||||
* @uiDefault FileChooser.detailsViewActionLabelText String
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatFileChooserUI
|
||||
extends MetalFileChooserUI
|
||||
{
|
||||
private final FlatFileView fileView = new FlatFileView();
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatFileChooserUI( (JFileChooser) c );
|
||||
}
|
||||
@@ -110,6 +143,40 @@ public class FlatFileChooserUI
|
||||
super( filechooser );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installComponents( JFileChooser fc ) {
|
||||
super.installComponents( fc );
|
||||
|
||||
patchUI( fc );
|
||||
}
|
||||
|
||||
private void patchUI( JFileChooser fc ) {
|
||||
// turn top-right buttons into toolbar buttons
|
||||
Component topPanel = fc.getComponent( 0 );
|
||||
if( (topPanel instanceof JPanel) &&
|
||||
(((JPanel)topPanel).getLayout() instanceof BorderLayout) )
|
||||
{
|
||||
Component topButtonPanel = ((JPanel)topPanel).getComponent( 0 );
|
||||
if( (topButtonPanel instanceof JPanel) &&
|
||||
(((JPanel)topButtonPanel).getLayout() instanceof BoxLayout) )
|
||||
{
|
||||
Insets margin = UIManager.getInsets( "Button.margin" );
|
||||
Component[] comps = ((JPanel)topButtonPanel).getComponents();
|
||||
for( int i = comps.length - 1; i >= 0; i-- ) {
|
||||
Component c = comps[i];
|
||||
if( c instanceof JButton || c instanceof JToggleButton ) {
|
||||
AbstractButton b = (AbstractButton)c;
|
||||
b.putClientProperty( FlatClientProperties.BUTTON_TYPE,
|
||||
FlatClientProperties.BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||
b.setMargin( margin );
|
||||
b.setFocusable( false );
|
||||
} else if( c instanceof Box.Filler )
|
||||
((JPanel)topButtonPanel).remove( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return UIScale.scale( super.getPreferredSize( c ) );
|
||||
@@ -119,4 +186,50 @@ public class FlatFileChooserUI
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return UIScale.scale( super.getMinimumSize( c ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileView getFileView( JFileChooser fc ) {
|
||||
return fileView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearIconCache() {
|
||||
fileView.clearIconCache();
|
||||
}
|
||||
|
||||
//---- class FlatFileView -------------------------------------------------
|
||||
|
||||
private class FlatFileView
|
||||
extends BasicFileView
|
||||
{
|
||||
@Override
|
||||
public Icon getIcon( File f ) {
|
||||
// get cached icon
|
||||
Icon icon = getCachedIcon( f );
|
||||
if( icon != null )
|
||||
return icon;
|
||||
|
||||
// get system icon
|
||||
if( f != null ) {
|
||||
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
||||
|
||||
if( icon != null ) {
|
||||
if( icon instanceof ImageIcon )
|
||||
icon = new ScaledImageIcon( (ImageIcon) icon );
|
||||
cacheIcon( f, icon );
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
// get default icon
|
||||
icon = super.getIcon( f );
|
||||
|
||||
if( icon instanceof ImageIcon ) {
|
||||
icon = new ScaledImageIcon( (ImageIcon) icon );
|
||||
cacheIcon( f, icon );
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,16 @@ public class FlatInternalFrameUI
|
||||
private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||
private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||
private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||
private final boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
||||
|
||||
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
||||
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
||||
UIManager.getInsets( "InternalFrame.activeDropShadowInsets" ),
|
||||
FlatUIUtils.getUIFloat( "InternalFrame.activeDropShadowOpacity", 0.5f ) );
|
||||
private final FlatDropShadowBorder inactiveDropShadowBorder = new FlatDropShadowBorder(
|
||||
UIManager.getColor( "InternalFrame.inactiveDropShadowColor" ),
|
||||
UIManager.getInsets( "InternalFrame.inactiveDropShadowInsets" ),
|
||||
FlatUIUtils.getUIFloat( "InternalFrame.inactiveDropShadowOpacity", 0.5f ) );
|
||||
|
||||
public FlatInternalFrameBorder() {
|
||||
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
||||
@@ -137,16 +147,31 @@ public class FlatInternalFrameUI
|
||||
Insets insets = getBorderInsets( c );
|
||||
float lineWidth = scale( (float) borderLineWidth );
|
||||
|
||||
float rx = x + insets.left - lineWidth;
|
||||
float ry = y + insets.top - lineWidth;
|
||||
float rwidth = width - insets.left - insets.right + (lineWidth * 2);
|
||||
float rheight = height - insets.top - insets.bottom + (lineWidth * 2);
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.setColor( f.isSelected() ? activeBorderColor : inactiveBorderColor );
|
||||
g2.fill( FlatUIUtils.createRectangle(
|
||||
x + insets.left - lineWidth,
|
||||
y + insets.top - lineWidth,
|
||||
width - insets.left - insets.right + (lineWidth * 2),
|
||||
height - insets.top - insets.bottom + (lineWidth * 2),
|
||||
lineWidth ) );
|
||||
|
||||
// paint drop shadow
|
||||
if( dropShadowPainted ) {
|
||||
FlatDropShadowBorder dropShadowBorder = f.isSelected()
|
||||
? activeDropShadowBorder : inactiveDropShadowBorder;
|
||||
|
||||
Insets dropShadowInsets = dropShadowBorder.getBorderInsets();
|
||||
dropShadowBorder.paintBorder( c, g2,
|
||||
(int) rx - dropShadowInsets.left,
|
||||
(int) ry - dropShadowInsets.top,
|
||||
(int) rwidth + dropShadowInsets.left + dropShadowInsets.right,
|
||||
(int) rheight + dropShadowInsets.top + dropShadowInsets.bottom );
|
||||
}
|
||||
|
||||
// paint border
|
||||
g2.fill( FlatUIUtils.createRectangle( rx, ry, rwidth, rheight, lineWidth ) );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -48,6 +48,14 @@ public class FlatLineBorder
|
||||
this.lineThickness = lineThickness;
|
||||
}
|
||||
|
||||
public Color getLineColor() {
|
||||
return lineColor;
|
||||
}
|
||||
|
||||
public float getLineThickness() {
|
||||
return lineThickness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
|
||||
@@ -16,9 +16,20 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.ActionMapUIResource;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuBar}.
|
||||
@@ -38,4 +49,45 @@ public class FlatMenuBarUI
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatMenuBarUI();
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING: This class is not used on macOS if screen menu bar is enabled.
|
||||
* Do not add any functionality here.
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void installKeyboardActions() {
|
||||
super.installKeyboardActions();
|
||||
|
||||
ActionMap map = SwingUtilities.getUIActionMap( menuBar );
|
||||
if( map == null ) {
|
||||
map = new ActionMapUIResource();
|
||||
SwingUtilities.replaceUIActionMap( menuBar, map );
|
||||
}
|
||||
map.put( "takeFocus", new TakeFocus() );
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Activates the menu bar and shows mnemonics.
|
||||
* On Windows, the popup of the first menu is not shown.
|
||||
* On other platforms, the popup of the first menu is shown.
|
||||
*/
|
||||
private static class TakeFocus
|
||||
extends AbstractAction
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
JMenuBar menuBar = (JMenuBar) e.getSource();
|
||||
JMenu menu = menuBar.getMenu( 0 );
|
||||
if( menu != null ) {
|
||||
MenuSelectionManager.defaultManager().setSelectedPath( SystemInfo.IS_WINDOWS
|
||||
? new MenuElement[] { menuBar, menu }
|
||||
: new MenuElement[] { menuBar, menu, menu.getPopupMenu() } );
|
||||
|
||||
FlatLaf.showMnemonics( menuBar );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.text.View;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
|
||||
/**
|
||||
* Renderer for menu items.
|
||||
*
|
||||
* @uiDefault MenuItem.minimumWidth int
|
||||
* @uiDefault MenuItem.minimumIconSize Dimension
|
||||
* @uiDefault MenuItem.textAcceleratorGap int
|
||||
* @uiDefault MenuItem.textNoAcceleratorGap int
|
||||
* @uiDefault MenuItem.acceleratorArrowGap int
|
||||
* @uiDefault MenuItem.checkBackground Color
|
||||
* @uiDefault MenuItem.underlineSelectionBackground Color
|
||||
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
||||
* @uiDefault MenuItem.underlineSelectionColor Color
|
||||
* @uiDefault MenuItem.underlineSelectionHeight Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMenuItemRenderer
|
||||
{
|
||||
protected final JMenuItem menuItem;
|
||||
protected final Icon checkIcon;
|
||||
protected final Icon arrowIcon;
|
||||
protected final Font acceleratorFont;
|
||||
protected final String acceleratorDelimiter;
|
||||
|
||||
protected final int minimumWidth = UIManager.getInt( "MenuItem.minimumWidth" );
|
||||
protected final Dimension minimumIconSize;
|
||||
protected final int textAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textAcceleratorGap", 28 );
|
||||
protected final int textNoAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textNoAcceleratorGap", 6 );
|
||||
protected final int acceleratorArrowGap = FlatUIUtils.getUIInt( "MenuItem.acceleratorArrowGap", 2 );
|
||||
|
||||
protected final Color checkBackground = UIManager.getColor( "MenuItem.checkBackground" );
|
||||
protected final Insets checkMargins = UIManager.getInsets( "MenuItem.checkMargins" );
|
||||
|
||||
protected final Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
|
||||
protected final Color underlineSelectionCheckBackground = UIManager.getColor( "MenuItem.underlineSelectionCheckBackground" );
|
||||
protected final Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
|
||||
protected final int underlineSelectionHeight = UIManager.getInt( "MenuItem.underlineSelectionHeight" );
|
||||
|
||||
protected FlatMenuItemRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
||||
Font acceleratorFont, String acceleratorDelimiter )
|
||||
{
|
||||
this.menuItem = menuItem;
|
||||
this.checkIcon = checkIcon;
|
||||
this.arrowIcon = arrowIcon;
|
||||
this.acceleratorFont = acceleratorFont;
|
||||
this.acceleratorDelimiter = acceleratorDelimiter;
|
||||
|
||||
Dimension minimumIconSize = UIManager.getDimension( "MenuItem.minimumIconSize" );
|
||||
this.minimumIconSize = (minimumIconSize != null) ? minimumIconSize : new Dimension( 16, 16 );
|
||||
}
|
||||
|
||||
protected Dimension getPreferredMenuItemSize() {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
boolean isTopLevelMenu = isTopLevelMenu( menuItem );
|
||||
|
||||
Rectangle viewRect = new Rectangle( 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE );
|
||||
Rectangle iconRect = new Rectangle();
|
||||
Rectangle textRect = new Rectangle();
|
||||
|
||||
// layout icon and text
|
||||
SwingUtilities.layoutCompoundLabel( menuItem,
|
||||
menuItem.getFontMetrics( menuItem.getFont() ), menuItem.getText(), getIconForLayout(),
|
||||
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
||||
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
||||
viewRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
||||
|
||||
// union icon and text rectangles
|
||||
Rectangle labelRect = iconRect.union( textRect );
|
||||
width += labelRect.width;
|
||||
height = Math.max( labelRect.height, height );
|
||||
|
||||
// accelerator size
|
||||
String accelText = getAcceleratorText();
|
||||
if( accelText != null ) {
|
||||
// gap between text and accelerator
|
||||
width += scale( !isTopLevelMenu ? textAcceleratorGap : menuItem.getIconTextGap() );
|
||||
|
||||
FontMetrics accelFm = menuItem.getFontMetrics( acceleratorFont );
|
||||
width += SwingUtilities.computeStringWidth( accelFm, accelText );
|
||||
height = Math.max( accelFm.getHeight(), height );
|
||||
}
|
||||
|
||||
// arrow size
|
||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
||||
// gap between text and arrow
|
||||
if( accelText == null )
|
||||
width += scale( textNoAcceleratorGap );
|
||||
|
||||
// gap between accelerator and arrow
|
||||
width += scale( acceleratorArrowGap );
|
||||
|
||||
width += arrowIcon.getIconWidth();
|
||||
height = Math.max( arrowIcon.getIconHeight(), height );
|
||||
}
|
||||
|
||||
// add insets
|
||||
Insets insets = menuItem.getInsets();
|
||||
width += insets.left + insets.right;
|
||||
height += insets.top + insets.bottom;
|
||||
|
||||
// minimum width
|
||||
if( !isTopLevelMenu ) {
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( menuItem, this.minimumWidth );
|
||||
width = Math.max( width, scale( minimumWidth ) );
|
||||
}
|
||||
|
||||
return new Dimension( width, height );
|
||||
}
|
||||
|
||||
private void layout( Rectangle viewRect, Rectangle iconRect, Rectangle textRect,
|
||||
Rectangle accelRect, Rectangle arrowRect, Rectangle labelRect )
|
||||
{
|
||||
boolean isTopLevelMenu = isTopLevelMenu( menuItem );
|
||||
|
||||
// layout arrow
|
||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
||||
arrowRect.width = arrowIcon.getIconWidth();
|
||||
arrowRect.height = arrowIcon.getIconHeight();
|
||||
} else
|
||||
arrowRect.setSize( 0, 0 );
|
||||
arrowRect.y = viewRect.y + centerOffset( viewRect.height, arrowRect.height );
|
||||
|
||||
// layout accelerator
|
||||
String accelText = getAcceleratorText();
|
||||
if( accelText != null ) {
|
||||
FontMetrics accelFm = menuItem.getFontMetrics( acceleratorFont );
|
||||
accelRect.width = SwingUtilities.computeStringWidth( accelFm, accelText );
|
||||
accelRect.height = accelFm.getHeight();
|
||||
|
||||
accelRect.y = viewRect.y + centerOffset( viewRect.height, accelRect.height );
|
||||
} else
|
||||
accelRect.setBounds( 0, 0, 0, 0 );
|
||||
|
||||
// compute horizontal positions of accelerator and arrow
|
||||
int accelArrowGap = !isTopLevelMenu ? scale( acceleratorArrowGap ) : 0;
|
||||
if( menuItem.getComponentOrientation().isLeftToRight() ) {
|
||||
// left-to-right
|
||||
arrowRect.x = viewRect.x + viewRect.width - arrowRect.width;
|
||||
accelRect.x = arrowRect.x - accelArrowGap - accelRect.width;
|
||||
} else {
|
||||
// right-to-left
|
||||
arrowRect.x = viewRect.x;
|
||||
accelRect.x = arrowRect.x + accelArrowGap + arrowRect.width;
|
||||
}
|
||||
|
||||
// width of accelerator, arrow and gap
|
||||
int accelArrowWidth = accelRect.width + arrowRect.width;
|
||||
if( accelText != null )
|
||||
accelArrowWidth += scale( !isTopLevelMenu ? textAcceleratorGap : menuItem.getIconTextGap() );
|
||||
if( !isTopLevelMenu && arrowIcon != null ) {
|
||||
if( accelText == null )
|
||||
accelArrowWidth += scale( textNoAcceleratorGap );
|
||||
accelArrowWidth += scale( acceleratorArrowGap );
|
||||
}
|
||||
|
||||
// label rectangle is view rectangle subtracted by accelerator, arrow and gap
|
||||
labelRect.setBounds( viewRect );
|
||||
labelRect.width -= accelArrowWidth;
|
||||
if( !menuItem.getComponentOrientation().isLeftToRight() )
|
||||
labelRect.x += accelArrowWidth;
|
||||
|
||||
// layout icon and text
|
||||
SwingUtilities.layoutCompoundLabel( menuItem,
|
||||
menuItem.getFontMetrics( menuItem.getFont() ), menuItem.getText(), getIconForLayout(),
|
||||
menuItem.getVerticalAlignment(), menuItem.getHorizontalAlignment(),
|
||||
menuItem.getVerticalTextPosition(), menuItem.getHorizontalTextPosition(),
|
||||
labelRect, iconRect, textRect, scale( menuItem.getIconTextGap() ) );
|
||||
}
|
||||
|
||||
private static int centerOffset( int wh1, int wh2 ) {
|
||||
return (wh1 / 2) - (wh2 / 2);
|
||||
}
|
||||
|
||||
protected void paintMenuItem( Graphics g, Color selectionBackground, Color selectionForeground,
|
||||
Color disabledForeground, Color acceleratorForeground, Color acceleratorSelectionForeground )
|
||||
{
|
||||
Rectangle viewRect = new Rectangle( menuItem.getWidth(), menuItem.getHeight() );
|
||||
|
||||
// subtract insets
|
||||
Insets insets = menuItem.getInsets();
|
||||
viewRect.x += insets.left;
|
||||
viewRect.y += insets.top;
|
||||
viewRect.width -= (insets.left + insets.right);
|
||||
viewRect.height -= (insets.top + insets.bottom);
|
||||
|
||||
Rectangle iconRect = new Rectangle();
|
||||
Rectangle textRect = new Rectangle();
|
||||
Rectangle accelRect = new Rectangle();
|
||||
Rectangle arrowRect = new Rectangle();
|
||||
Rectangle labelRect = new Rectangle();
|
||||
|
||||
layout( viewRect, iconRect, textRect, accelRect, arrowRect, labelRect );
|
||||
|
||||
/*debug
|
||||
g.setColor( Color.green ); g.drawRect( viewRect.x, viewRect.y, viewRect.width - 1, viewRect.height - 1 );
|
||||
g.setColor( Color.red ); g.drawRect( labelRect.x, labelRect.y, labelRect.width - 1, labelRect.height - 1 );
|
||||
g.setColor( Color.blue ); g.drawRect( iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1 );
|
||||
g.setColor( Color.cyan ); g.drawRect( textRect.x, textRect.y, textRect.width - 1, textRect.height - 1 );
|
||||
g.setColor( Color.magenta ); g.drawRect( accelRect.x, accelRect.y, accelRect.width - 1, accelRect.height - 1 );
|
||||
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
|
||||
debug*/
|
||||
|
||||
paintBackground( g, selectionBackground );
|
||||
paintIcon( g, iconRect, getIconForPainting() );
|
||||
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
|
||||
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
|
||||
if( !isTopLevelMenu( menuItem ) )
|
||||
paintArrowIcon( g, arrowRect, arrowIcon );
|
||||
}
|
||||
|
||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
||||
boolean armedOrSelected = isArmedOrSelected( menuItem );
|
||||
if( menuItem.isOpaque() || armedOrSelected ) {
|
||||
int width = menuItem.getWidth();
|
||||
int height = menuItem.getHeight();
|
||||
|
||||
// paint background
|
||||
g.setColor( armedOrSelected
|
||||
? (isUnderlineSelection() ? underlineSelectionBackground : selectionBackground)
|
||||
: menuItem.getBackground() );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
|
||||
// paint underline
|
||||
if( armedOrSelected && isUnderlineSelection() ) {
|
||||
int underlineHeight = scale( underlineSelectionHeight );
|
||||
g.setColor( underlineSelectionColor );
|
||||
if( isTopLevelMenu( menuItem ) ) {
|
||||
// paint underline at bottom
|
||||
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
|
||||
} else if( menuItem.getComponentOrientation().isLeftToRight() ) {
|
||||
// paint underline at left side
|
||||
g.fillRect( 0, 0, underlineHeight, height );
|
||||
} else {
|
||||
// paint underline at right side
|
||||
g.fillRect( width - underlineHeight, 0, underlineHeight, height );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintIcon( Graphics g, Rectangle iconRect, Icon icon ) {
|
||||
// if checkbox/radiobutton menu item is selected and also has a custom icon,
|
||||
// then use filled icon background to indicate selection (instead of using checkIcon)
|
||||
if( menuItem.isSelected() && checkIcon != null && icon != checkIcon ) {
|
||||
Rectangle r = FlatUIUtils.addInsets( iconRect, scale( checkMargins ) );
|
||||
g.setColor( isUnderlineSelection() ? underlineSelectionCheckBackground : checkBackground );
|
||||
g.fillRect( r.x, r.y, r.width, r.height );
|
||||
}
|
||||
|
||||
paintIcon( g, menuItem, icon, iconRect );
|
||||
}
|
||||
|
||||
protected void paintText( Graphics g, Rectangle textRect, String text, Color selectionForeground, Color disabledForeground ) {
|
||||
View htmlView = (View) menuItem.getClientProperty( BasicHTML.propertyKey );
|
||||
if( htmlView != null ) {
|
||||
paintHTMLText( g, menuItem, textRect, htmlView, isUnderlineSelection() ? null : selectionForeground );
|
||||
return;
|
||||
}
|
||||
|
||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
|
||||
Color foreground = menuItem.getForeground();
|
||||
|
||||
paintText( g, menuItem, textRect, text, mnemonicIndex, menuItem.getFont(),
|
||||
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
|
||||
}
|
||||
|
||||
protected void paintAccelerator( Graphics g, Rectangle accelRect, String accelText,
|
||||
Color foreground, Color selectionForeground, Color disabledForeground )
|
||||
{
|
||||
paintText( g, menuItem, accelRect, accelText, -1, acceleratorFont,
|
||||
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
|
||||
}
|
||||
|
||||
protected void paintArrowIcon( Graphics g, Rectangle arrowRect, Icon arrowIcon ) {
|
||||
paintIcon( g, menuItem, arrowIcon, arrowRect );
|
||||
}
|
||||
|
||||
protected static void paintIcon( Graphics g, JMenuItem menuItem, Icon icon, Rectangle iconRect ) {
|
||||
if( icon == null )
|
||||
return;
|
||||
|
||||
// center because the real icon may be smaller than dimension in iconRect
|
||||
int x = iconRect.x + centerOffset( iconRect.width, icon.getIconWidth() );
|
||||
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
||||
|
||||
// paint
|
||||
icon.paintIcon( menuItem, g, x, y );
|
||||
}
|
||||
|
||||
protected static void paintText( Graphics g, JMenuItem menuItem,
|
||||
Rectangle textRect, String text, int mnemonicIndex, Font font,
|
||||
Color foreground, Color selectionForeground, Color disabledForeground )
|
||||
{
|
||||
if( text == null || text.isEmpty() )
|
||||
return;
|
||||
|
||||
FontMetrics fm = menuItem.getFontMetrics( font );
|
||||
|
||||
Font oldFont = g.getFont();
|
||||
g.setFont( font );
|
||||
g.setColor( !menuItem.isEnabled()
|
||||
? disabledForeground
|
||||
: (isArmedOrSelected( menuItem )
|
||||
? selectionForeground
|
||||
: foreground) );
|
||||
|
||||
FlatUIUtils.drawStringUnderlineCharAt( menuItem, g, text, mnemonicIndex,
|
||||
textRect.x, textRect.y + fm.getAscent() );
|
||||
|
||||
g.setFont( oldFont );
|
||||
}
|
||||
|
||||
protected static void paintHTMLText( Graphics g, JMenuItem menuItem,
|
||||
Rectangle textRect, View htmlView, Color selectionForeground )
|
||||
{
|
||||
if( isArmedOrSelected( menuItem ) && selectionForeground != null )
|
||||
g = new GraphicsProxyWithTextColor( (Graphics2D) g, selectionForeground );
|
||||
|
||||
htmlView.paint( g, textRect );
|
||||
}
|
||||
|
||||
protected static boolean isArmedOrSelected( JMenuItem menuItem ) {
|
||||
return menuItem.isArmed() || (menuItem instanceof JMenu && menuItem.isSelected());
|
||||
}
|
||||
|
||||
protected static boolean isTopLevelMenu( JMenuItem menuItem ) {
|
||||
return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu();
|
||||
}
|
||||
|
||||
private boolean isUnderlineSelection() {
|
||||
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
|
||||
}
|
||||
|
||||
private Icon getIconForPainting() {
|
||||
Icon icon = menuItem.getIcon();
|
||||
|
||||
if( icon == null && checkIcon != null && !isTopLevelMenu( menuItem ) )
|
||||
return checkIcon;
|
||||
|
||||
if( icon == null )
|
||||
return null;
|
||||
|
||||
if( !menuItem.isEnabled() )
|
||||
return menuItem.getDisabledIcon();
|
||||
|
||||
if( menuItem.getModel().isPressed() && menuItem.isArmed() ) {
|
||||
Icon pressedIcon = menuItem.getPressedIcon();
|
||||
if( pressedIcon != null )
|
||||
return pressedIcon;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private Icon getIconForLayout() {
|
||||
Icon icon = menuItem.getIcon();
|
||||
|
||||
if( isTopLevelMenu( menuItem ) )
|
||||
return (icon != null) ? new MinSizeIcon( icon ) : null;
|
||||
|
||||
return new MinSizeIcon( (icon != null) ? icon : checkIcon );
|
||||
}
|
||||
|
||||
private KeyStroke cachedAccelerator;
|
||||
private String cachedAcceleratorText;
|
||||
|
||||
private String getAcceleratorText() {
|
||||
KeyStroke accelerator = menuItem.getAccelerator();
|
||||
if( accelerator == null )
|
||||
return null;
|
||||
|
||||
if( accelerator == cachedAccelerator )
|
||||
return cachedAcceleratorText;
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
int modifiers = accelerator.getModifiers();
|
||||
if( modifiers != 0 )
|
||||
buf.append( InputEvent.getModifiersExText( modifiers ) ).append( acceleratorDelimiter );
|
||||
|
||||
int keyCode = accelerator.getKeyCode();
|
||||
if( keyCode != 0 )
|
||||
buf.append( KeyEvent.getKeyText( keyCode ) );
|
||||
else
|
||||
buf.append( accelerator.getKeyChar() );
|
||||
|
||||
cachedAccelerator = accelerator;
|
||||
cachedAcceleratorText = buf.toString();
|
||||
|
||||
return cachedAcceleratorText;
|
||||
}
|
||||
|
||||
//---- class MinSizeIcon --------------------------------------------------
|
||||
|
||||
private class MinSizeIcon
|
||||
implements Icon
|
||||
{
|
||||
private final Icon delegate;
|
||||
|
||||
MinSizeIcon( Icon delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
int iconWidth = (delegate != null) ? delegate.getIconWidth() : 0;
|
||||
return Math.max( iconWidth, scale( minimumIconSize.width ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
int iconHeight = (delegate != null) ? delegate.getIconHeight() : 0;
|
||||
return Math.max( iconHeight, scale( minimumIconSize.height ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
}
|
||||
}
|
||||
|
||||
//---- class GraphicsProxyWithTextColor -----------------------------------
|
||||
|
||||
private static class GraphicsProxyWithTextColor
|
||||
extends Graphics2DProxy
|
||||
{
|
||||
private final Color textColor;
|
||||
|
||||
GraphicsProxyWithTextColor( Graphics2D delegate, Color textColor ) {
|
||||
super( delegate );
|
||||
this.textColor = textColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( String str, int x, int y ) {
|
||||
Paint oldPaint = getPaint();
|
||||
setPaint( textColor );
|
||||
super.drawString( str, x, y );
|
||||
setPaint( oldPaint );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( String str, float x, float y ) {
|
||||
Paint oldPaint = getPaint();
|
||||
setPaint( textColor );
|
||||
super.drawString( str, x, y );
|
||||
setPaint( oldPaint );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( AttributedCharacterIterator iterator, int x, int y ) {
|
||||
Paint oldPaint = getPaint();
|
||||
setPaint( textColor );
|
||||
super.drawString( iterator, x, y );
|
||||
setPaint( oldPaint );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( AttributedCharacterIterator iterator, float x, float y ) {
|
||||
Paint oldPaint = getPaint();
|
||||
setPaint( textColor );
|
||||
super.drawString( iterator, x, y );
|
||||
setPaint( oldPaint );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawChars( char[] data, int offset, int length, int x, int y ) {
|
||||
Paint oldPaint = getPaint();
|
||||
setPaint( textColor );
|
||||
super.drawChars( data, offset, length, x, y );
|
||||
setPaint( oldPaint );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,48 +16,47 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
|
||||
*
|
||||
* <!-- BasicMenuItemUI -->
|
||||
*
|
||||
* @uiDefault MenuItem.font Font
|
||||
* @uiDefault MenuItem.background Color
|
||||
* @uiDefault MenuItem.foreground Color
|
||||
* @uiDefault MenuItem.disabledForeground Color
|
||||
* @uiDefault MenuItem.selectionBackground Color
|
||||
* @uiDefault MenuItem.selectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorForeground Color
|
||||
* @uiDefault MenuItem.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault MenuItem.border Border
|
||||
* @uiDefault MenuItem.borderPainted boolean
|
||||
* @uiDefault MenuItem.margin Insets
|
||||
* @uiDefault MenuItem.arrowIcon Icon
|
||||
* @uiDefault MenuItem.checkIcon Icon
|
||||
* @uiDefault MenuItem.opaque boolean
|
||||
* @uiDefault MenuItem.evenHeight boolean
|
||||
* @uiDefault MenuItem.font Font
|
||||
* @uiDefault MenuItem.background Color
|
||||
* @uiDefault MenuItem.foreground Color
|
||||
* @uiDefault MenuItem.disabledForeground Color
|
||||
* @uiDefault MenuItem.selectionBackground Color
|
||||
* @uiDefault MenuItem.selectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorForeground Color
|
||||
* @uiDefault MenuItem.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault MenuItem.border Border
|
||||
* @uiDefault MenuItem.borderPainted boolean
|
||||
* @uiDefault MenuItem.margin Insets
|
||||
* @uiDefault MenuItem.arrowIcon Icon
|
||||
* @uiDefault MenuItem.checkIcon Icon
|
||||
* @uiDefault MenuItem.opaque boolean
|
||||
*
|
||||
* <!-- FlatMenuItemUI -->
|
||||
*
|
||||
* @uiDefault MenuItem.iconTextGap int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMenuItemUI
|
||||
extends BasicMenuItemUI
|
||||
{
|
||||
private FlatMenuItemRenderer renderer;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatMenuItemUI();
|
||||
}
|
||||
@@ -66,42 +65,30 @@ public class FlatMenuItemUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
// scale
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
}
|
||||
LookAndFeel.installProperty( menuItem, "iconTextGap", FlatUIUtils.getUIInt( "MenuItem.iconTextGap", 4 ) );
|
||||
|
||||
/**
|
||||
* Scale defaultTextIconGap again if iconTextGap property has changed.
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener( c );
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
if( e.getPropertyName() == "iconTextGap" )
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
renderer = createRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
renderer = null;
|
||||
}
|
||||
|
||||
public static void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect,
|
||||
String text, Color disabledForeground, Color selectionForeground )
|
||||
{
|
||||
FontMetrics fm = menuItem.getFontMetrics( menuItem.getFont() );
|
||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
ButtonModel model = menuItem.getModel();
|
||||
g.setColor( !model.isEnabled()
|
||||
? disabledForeground
|
||||
: (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())
|
||||
? selectionForeground
|
||||
: menuItem.getForeground()) );
|
||||
@Override
|
||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||
return renderer.getPreferredMenuItemSize();
|
||||
}
|
||||
|
||||
FlatUIUtils.drawStringUnderlineCharAt( menuItem, g, text, mnemonicIndex,
|
||||
textRect.x, textRect.y + fm.getAscent() );
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
renderer.paintMenuItem( g, selectionBackground, selectionForeground, disabledForeground,
|
||||
acceleratorForeground, acceleratorSelectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
@@ -36,30 +37,30 @@ import javax.swing.plaf.basic.BasicMenuUI;
|
||||
*
|
||||
* <!-- BasicMenuUI -->
|
||||
*
|
||||
* @uiDefault Menu.font Font
|
||||
* @uiDefault Menu.background Color
|
||||
* @uiDefault Menu.foreground Color
|
||||
* @uiDefault Menu.disabledForeground Color
|
||||
* @uiDefault Menu.selectionBackground Color
|
||||
* @uiDefault Menu.selectionForeground Color
|
||||
* @uiDefault Menu.acceleratorForeground Color
|
||||
* @uiDefault Menu.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault Menu.border Border
|
||||
* @uiDefault Menu.borderPainted boolean
|
||||
* @uiDefault Menu.margin Insets
|
||||
* @uiDefault Menu.arrowIcon Icon
|
||||
* @uiDefault Menu.checkIcon Icon
|
||||
* @uiDefault Menu.opaque boolean
|
||||
* @uiDefault Menu.evenHeight boolean
|
||||
* @uiDefault Menu.crossMenuMnemonic boolean default is false
|
||||
* @uiDefault Menu.useMenuBarBackgroundForTopLevel boolean default is false
|
||||
* @uiDefault MenuBar.background Color used if Menu.useMenuBarBackgroundForTopLevel is true
|
||||
* @uiDefault Menu.font Font
|
||||
* @uiDefault Menu.background Color
|
||||
* @uiDefault Menu.foreground Color
|
||||
* @uiDefault Menu.disabledForeground Color
|
||||
* @uiDefault Menu.selectionBackground Color
|
||||
* @uiDefault Menu.selectionForeground Color
|
||||
* @uiDefault Menu.acceleratorForeground Color
|
||||
* @uiDefault Menu.acceleratorSelectionForeground Color
|
||||
* @uiDefault MenuItem.acceleratorFont Font defaults to MenuItem.font
|
||||
* @uiDefault MenuItem.acceleratorDelimiter String
|
||||
* @uiDefault Menu.border Border
|
||||
* @uiDefault Menu.borderPainted boolean
|
||||
* @uiDefault Menu.margin Insets
|
||||
* @uiDefault Menu.arrowIcon Icon
|
||||
* @uiDefault Menu.checkIcon Icon
|
||||
* @uiDefault Menu.opaque boolean
|
||||
* @uiDefault Menu.crossMenuMnemonic boolean default is false
|
||||
* @uiDefault Menu.useMenuBarBackgroundForTopLevel boolean default is false
|
||||
* @uiDefault MenuBar.background Color used if Menu.useMenuBarBackgroundForTopLevel is true
|
||||
*
|
||||
* <!-- FlatMenuUI -->
|
||||
*
|
||||
* @uiDefault MenuBar.hoverBackground Color
|
||||
* @uiDefault MenuItem.iconTextGap int
|
||||
* @uiDefault MenuBar.hoverBackground Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -67,6 +68,7 @@ public class FlatMenuUI
|
||||
extends BasicMenuUI
|
||||
{
|
||||
private Color hoverBackground;
|
||||
private FlatMenuItemRenderer renderer;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatMenuUI();
|
||||
@@ -76,12 +78,12 @@ public class FlatMenuUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
LookAndFeel.installProperty( menuItem, "iconTextGap", FlatUIUtils.getUIInt( "MenuItem.iconTextGap", 4 ) );
|
||||
|
||||
menuItem.setRolloverEnabled( true );
|
||||
|
||||
hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
||||
|
||||
// scale
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
renderer = createRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,19 +91,11 @@ public class FlatMenuUI
|
||||
super.uninstallDefaults();
|
||||
|
||||
hoverBackground = null;
|
||||
renderer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale defaultTextIconGap again if iconTextGap property has changed.
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener( c );
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
if( e.getPropertyName() == "iconTextGap" )
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,19 +124,37 @@ public class FlatMenuUI
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g, JMenuItem menuItem, Color bgColor ) {
|
||||
ButtonModel model = menuItem.getModel();
|
||||
if( model.isArmed() || model.isSelected() ) {
|
||||
super.paintBackground( g, menuItem, bgColor );
|
||||
} else if( model.isRollover() && model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||
FlatUIUtils.setColor( g, hoverBackground, menuItem.getBackground() );
|
||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||
} else
|
||||
super.paintBackground( g, menuItem, bgColor );
|
||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||
return renderer.getPreferredMenuItemSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
renderer.paintMenuItem( g, selectionBackground, selectionForeground, disabledForeground,
|
||||
acceleratorForeground, acceleratorSelectionForeground );
|
||||
}
|
||||
|
||||
//---- class FlatMenuRenderer ---------------------------------------------
|
||||
|
||||
protected class FlatMenuRenderer
|
||||
extends FlatMenuItemRenderer
|
||||
{
|
||||
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
|
||||
Font acceleratorFont, String acceleratorDelimiter )
|
||||
{
|
||||
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g, Color selectionBackground ) {
|
||||
ButtonModel model = menuItem.getModel();
|
||||
if( model.isRollover() && !model.isArmed() && !model.isSelected() &&
|
||||
model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() )
|
||||
{
|
||||
FlatUIUtils.setColor( g, hoverBackground, menuItem.getBackground() );
|
||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||
} else
|
||||
super.paintBackground( g, selectionBackground );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
@@ -34,7 +33,6 @@ import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPasswordFieldUI;
|
||||
import javax.swing.text.Caret;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}.
|
||||
@@ -57,8 +55,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
*
|
||||
* <!-- FlatPasswordFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault PasswordField.placeholderForeground Color
|
||||
@@ -70,8 +66,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
public class FlatPasswordFieldUI
|
||||
extends BasicPasswordFieldUI
|
||||
{
|
||||
protected int arc;
|
||||
protected int focusWidth;
|
||||
protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
protected Color placeholderForeground;
|
||||
@@ -89,16 +83,14 @@ public class FlatPasswordFieldUI
|
||||
super.installDefaults();
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
arc = UIManager.getInt( "TextComponent.arc" );
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
|
||||
capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" );
|
||||
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", false );
|
||||
|
||||
MigLayoutVisualPadding.install( getComponent(), focusWidth );
|
||||
MigLayoutVisualPadding.install( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,14 +145,12 @@ public class FlatPasswordFieldUI
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
|
||||
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
|
||||
getComponent().repaint();
|
||||
FlatTextFieldUI.propertyChange( getComponent(), e );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintSafely( Graphics g ) {
|
||||
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, arc, isIntelliJTheme );
|
||||
FlatTextFieldUI.paintBackground( g, getComponent(), isIntelliJTheme );
|
||||
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||
paintCapsLock( g );
|
||||
super.paintSafely( g );
|
||||
@@ -184,18 +174,11 @@ public class FlatPasswordFieldUI
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getPreferredSize( c ), c );
|
||||
return FlatTextFieldUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getMinimumSize( c ), c );
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
|
||||
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
|
||||
return size;
|
||||
return FlatTextFieldUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.Popup;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* A popup factory that adds drop shadows to popups on Windows.
|
||||
* On macOS and Linux, heavy weight popups (without drop shadow) are produced and the
|
||||
* operating system automatically adds drop shadows.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPopupFactory
|
||||
extends PopupFactory
|
||||
{
|
||||
private Method java8getPopupMethod;
|
||||
private Method java9getPopupMethod;
|
||||
|
||||
@Override
|
||||
public Popup getPopup( Component owner, Component contents, int x, int y )
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if( !isDropShadowPainted( owner, contents ) )
|
||||
return new NonFlashingPopup( super.getPopup( owner, contents, x, y ), contents );
|
||||
|
||||
// macOS and Linux adds drop shadow to heavy weight popups
|
||||
if( SystemInfo.IS_MAC || SystemInfo.IS_LINUX ) {
|
||||
Popup popup = getHeavyWeightPopup( owner, contents, x, y );
|
||||
if( popup == null )
|
||||
popup = super.getPopup( owner, contents, x, y );
|
||||
return new NonFlashingPopup( popup, contents );
|
||||
}
|
||||
|
||||
// create drop shadow popup
|
||||
return new DropShadowPopup( super.getPopup( owner, contents, x, y ), owner, contents );
|
||||
}
|
||||
|
||||
private boolean isDropShadowPainted( Component owner, Component contents ) {
|
||||
Boolean b = isDropShadowPainted( owner );
|
||||
if( b != null )
|
||||
return b;
|
||||
|
||||
b = isDropShadowPainted( contents );
|
||||
if( b != null )
|
||||
return b;
|
||||
|
||||
return UIManager.getBoolean( "Popup.dropShadowPainted" );
|
||||
}
|
||||
|
||||
private Boolean isDropShadowPainted( Component c ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return null;
|
||||
|
||||
Object value = ((JComponent)c).getClientProperty( FlatClientProperties.POPUP_DROP_SHADOW_PAINTED );
|
||||
return (value instanceof Boolean ) ? (Boolean) value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* There is no API in Java 8 to force creation of heavy weight popups,
|
||||
* but it is possible with reflection. Java 9 provides a new method.
|
||||
*
|
||||
* When changing FlatLaf system requirements to Java 9+,
|
||||
* then this method can be replaced with:
|
||||
* return getPopup( owner, contents, x, y, true );
|
||||
*/
|
||||
private Popup getHeavyWeightPopup( Component owner, Component contents, int x, int y )
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
try {
|
||||
if( SystemInfo.IS_JAVA_9_OR_LATER ) {
|
||||
if( java9getPopupMethod == null ) {
|
||||
java9getPopupMethod = PopupFactory.class.getDeclaredMethod(
|
||||
"getPopup", Component.class, Component.class, int.class, int.class, boolean.class );
|
||||
}
|
||||
return (Popup) java9getPopupMethod.invoke( this, owner, contents, x, y, true );
|
||||
} else {
|
||||
// Java 8
|
||||
if( java8getPopupMethod == null ) {
|
||||
java8getPopupMethod = PopupFactory.class.getDeclaredMethod(
|
||||
"getPopup", Component.class, Component.class, int.class, int.class, int.class );
|
||||
java8getPopupMethod.setAccessible( true );
|
||||
}
|
||||
return (Popup) java8getPopupMethod.invoke( this, owner, contents, x, y, /*HEAVY_WEIGHT_POPUP*/ 2 );
|
||||
}
|
||||
} catch( NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException ex ) {
|
||||
// ignore
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class NonFlashingPopup ---------------------------------------------
|
||||
|
||||
private class NonFlashingPopup
|
||||
extends Popup
|
||||
{
|
||||
private Popup delegate;
|
||||
|
||||
// heavy weight
|
||||
protected Window popupWindow;
|
||||
private Color oldPopupWindowBackground;
|
||||
|
||||
NonFlashingPopup( Popup delegate, Component contents ) {
|
||||
this.delegate = delegate;
|
||||
|
||||
popupWindow = SwingUtilities.windowForComponent( contents );
|
||||
if( popupWindow != null ) {
|
||||
// heavy weight popup
|
||||
|
||||
// fix background flashing which may occur on some platforms
|
||||
// (e.g. macOS and Linux) when using dark theme
|
||||
oldPopupWindowBackground = popupWindow.getBackground();
|
||||
popupWindow.setBackground( contents.getBackground() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
delegate.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if( delegate != null ) {
|
||||
delegate.hide();
|
||||
delegate = null;
|
||||
}
|
||||
|
||||
if( popupWindow != null ) {
|
||||
// restore background so that it can not affect other LaFs (when switching)
|
||||
// because popup windows are cached and reused
|
||||
popupWindow.setBackground( oldPopupWindowBackground );
|
||||
popupWindow = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- class DropShadowPopup ----------------------------------------------
|
||||
|
||||
private class DropShadowPopup
|
||||
extends NonFlashingPopup
|
||||
{
|
||||
private final Component owner;
|
||||
|
||||
// light weight
|
||||
private JComponent lightComp;
|
||||
private Border oldBorder;
|
||||
private boolean oldOpaque;
|
||||
|
||||
// medium weight
|
||||
private Panel mediumWeightPanel;
|
||||
private JPanel dropShadowPanel;
|
||||
private ComponentListener mediumPanelListener;
|
||||
|
||||
// heavy weight
|
||||
private Popup dropShadowDelegate;
|
||||
private Window dropShadowWindow;
|
||||
private Color oldDropShadowWindowBackground;
|
||||
|
||||
DropShadowPopup( Popup delegate, Component owner, Component contents ) {
|
||||
super( delegate, contents );
|
||||
this.owner = owner;
|
||||
|
||||
Dimension size = contents.getPreferredSize();
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
return;
|
||||
|
||||
if( popupWindow != null ) {
|
||||
// heavy weight popup
|
||||
|
||||
// Since Java has a problem with sub-pixel text rendering on translucent
|
||||
// windows, we can not make the popup window translucent for the drop shadow.
|
||||
// (see https://bugs.openjdk.java.net/browse/JDK-8215980)
|
||||
// The solution is to create a second translucent window that paints
|
||||
// the drop shadow and is positioned behind the popup window.
|
||||
|
||||
// create panel that paints the drop shadow
|
||||
JPanel dropShadowPanel = new JPanel();
|
||||
dropShadowPanel.setBorder( createDropShadowBorder() );
|
||||
dropShadowPanel.setOpaque( false );
|
||||
|
||||
// set preferred size of drop shadow panel
|
||||
Dimension prefSize = popupWindow.getPreferredSize();
|
||||
Insets insets = dropShadowPanel.getInsets();
|
||||
dropShadowPanel.setPreferredSize( new Dimension(
|
||||
prefSize.width + insets.left + insets.right,
|
||||
prefSize.height + insets.top + insets.bottom ) );
|
||||
|
||||
// create heavy weight popup for drop shadow
|
||||
int x = popupWindow.getX() - insets.left;
|
||||
int y = popupWindow.getY() - insets.top;
|
||||
dropShadowDelegate = getHeavyWeightPopup( owner, dropShadowPanel, x, y );
|
||||
|
||||
// make drop shadow popup window translucent
|
||||
dropShadowWindow = SwingUtilities.windowForComponent( dropShadowPanel );
|
||||
if( dropShadowWindow != null ) {
|
||||
oldDropShadowWindowBackground = dropShadowWindow.getBackground();
|
||||
dropShadowWindow.setBackground( new Color( 0, true ) );
|
||||
}
|
||||
} else {
|
||||
mediumWeightPanel = (Panel) SwingUtilities.getAncestorOfClass( Panel.class, contents );
|
||||
if( mediumWeightPanel != null ) {
|
||||
// medium weight popup
|
||||
dropShadowPanel = new JPanel();
|
||||
dropShadowPanel.setBorder( createDropShadowBorder() );
|
||||
dropShadowPanel.setOpaque( false );
|
||||
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
|
||||
} else {
|
||||
// light weight popup
|
||||
Container p = contents.getParent();
|
||||
if( !(p instanceof JComponent) )
|
||||
return;
|
||||
|
||||
lightComp = (JComponent) p;
|
||||
oldBorder = lightComp.getBorder();
|
||||
oldOpaque = lightComp.isOpaque();
|
||||
lightComp.setBorder( createDropShadowBorder() );
|
||||
lightComp.setOpaque( false );
|
||||
lightComp.setSize( lightComp.getPreferredSize() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Border createDropShadowBorder() {
|
||||
return new FlatDropShadowBorder(
|
||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||
UIManager.getInsets( "Popup.dropShadowInsets" ),
|
||||
FlatUIUtils.getUIFloat( "Popup.dropShadowOpacity", 0.5f ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if( dropShadowDelegate != null )
|
||||
dropShadowDelegate.show();
|
||||
|
||||
if( mediumWeightPanel != null )
|
||||
showMediumWeightDropShadow();
|
||||
|
||||
super.show();
|
||||
|
||||
// fix location of light weight popup in case it has left or top drop shadow
|
||||
if( lightComp != null ) {
|
||||
Insets insets = lightComp.getInsets();
|
||||
if( insets.left != 0 || insets.top != 0 )
|
||||
lightComp.setLocation( lightComp.getX() - insets.left, lightComp.getY() - insets.top );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if( dropShadowDelegate != null ) {
|
||||
dropShadowDelegate.hide();
|
||||
dropShadowDelegate = null;
|
||||
}
|
||||
|
||||
if( mediumWeightPanel != null ) {
|
||||
hideMediumWeightDropShadow();
|
||||
dropShadowPanel = null;
|
||||
mediumWeightPanel = null;
|
||||
}
|
||||
|
||||
super.hide();
|
||||
|
||||
if( dropShadowWindow != null ) {
|
||||
dropShadowWindow.setBackground( oldDropShadowWindowBackground );
|
||||
dropShadowWindow = null;
|
||||
}
|
||||
|
||||
if( lightComp != null ) {
|
||||
lightComp.setBorder( oldBorder );
|
||||
lightComp.setOpaque( oldOpaque );
|
||||
lightComp = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void showMediumWeightDropShadow() {
|
||||
Window window = SwingUtilities.windowForComponent( owner );
|
||||
if( window == null )
|
||||
return;
|
||||
|
||||
if( !(window instanceof RootPaneContainer) )
|
||||
return;
|
||||
|
||||
dropShadowPanel.setVisible( false );
|
||||
|
||||
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||
layeredPane.add( dropShadowPanel, JLayeredPane.POPUP_LAYER, 0 );
|
||||
|
||||
mediumPanelListener = new ComponentListener() {
|
||||
@Override
|
||||
public void componentShown( ComponentEvent e ) {
|
||||
dropShadowPanel.setVisible( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden( ComponentEvent e ) {
|
||||
dropShadowPanel.setVisible( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved( ComponentEvent e ) {
|
||||
Point location = mediumWeightPanel.getLocation();
|
||||
Insets insets = dropShadowPanel.getInsets();
|
||||
dropShadowPanel.setLocation( location.x - insets.left, location.y - insets.top );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
|
||||
}
|
||||
};
|
||||
mediumWeightPanel.addComponentListener( mediumPanelListener );
|
||||
}
|
||||
|
||||
private void hideMediumWeightDropShadow() {
|
||||
mediumWeightPanel.removeComponentListener( mediumPanelListener );
|
||||
|
||||
Container parent = dropShadowPanel.getParent();
|
||||
if( parent != null ) {
|
||||
Rectangle bounds = dropShadowPanel.getBounds();
|
||||
parent.remove( dropShadowPanel );
|
||||
parent.repaint( bounds.x, bounds.y, bounds.width, bounds.height );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
|
||||
|
||||
@@ -46,13 +45,18 @@ import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
|
||||
* @uiDefault RadioButtonMenuItem.arrowIcon Icon
|
||||
* @uiDefault RadioButtonMenuItem.checkIcon Icon
|
||||
* @uiDefault RadioButtonMenuItem.opaque boolean
|
||||
* @uiDefault RadioButtonMenuItem.evenHeight boolean
|
||||
*
|
||||
* <!-- FlatRadioButtonMenuItemUI -->
|
||||
*
|
||||
* @uiDefault MenuItem.iconTextGap int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatRadioButtonMenuItemUI
|
||||
extends BasicRadioButtonMenuItemUI
|
||||
{
|
||||
private FlatMenuItemRenderer renderer;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatRadioButtonMenuItemUI();
|
||||
}
|
||||
@@ -61,25 +65,30 @@ public class FlatRadioButtonMenuItemUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
// scale
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
}
|
||||
LookAndFeel.installProperty( menuItem, "iconTextGap", FlatUIUtils.getUIInt( "MenuItem.iconTextGap", 4 ) );
|
||||
|
||||
/**
|
||||
* Scale defaultTextIconGap again if iconTextGap property has changed.
|
||||
*/
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener( c );
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
if( e.getPropertyName() == "iconTextGap" )
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
renderer = createRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
renderer = null;
|
||||
}
|
||||
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||
return renderer.getPreferredMenuItemSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
renderer.paintMenuItem( g, selectionBackground, selectionForeground, disabledForeground,
|
||||
acceleratorForeground, acceleratorSelectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.CellRendererPane;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
@@ -122,11 +121,10 @@ public class FlatRadioButtonUI
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
// fill background even if not opaque if
|
||||
// - contentAreaFilled is true and
|
||||
// - used as cell renderer (because of selection background)
|
||||
// - or if background was explicitly set to a non-UIResource color
|
||||
// - if background was explicitly set to a non-UIResource color
|
||||
if( !c.isOpaque() &&
|
||||
((AbstractButton)c).isContentAreaFilled() &&
|
||||
(c.getParent() instanceof CellRendererPane || !(c.getBackground() instanceof UIResource)))
|
||||
!(c.getBackground() instanceof UIResource) )
|
||||
{
|
||||
g.setColor( c.getBackground() );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
@@ -33,7 +32,7 @@ public class FlatRoundBorder
|
||||
protected final int arc = UIManager.getInt( "Component.arc" );
|
||||
|
||||
@Override
|
||||
protected float getArc( Component c ) {
|
||||
return scale( (float) arc );
|
||||
protected int getArc( Component c ) {
|
||||
return FlatUIUtils.isRoundRect( c ) ? Short.MAX_VALUE : arc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class FlatScrollPaneUI
|
||||
int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
LookAndFeel.installProperty( c, "opaque", focusWidth == 0 );
|
||||
|
||||
MigLayoutVisualPadding.install( scrollpane, focusWidth );
|
||||
MigLayoutVisualPadding.install( scrollpane );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,6 +40,7 @@ import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicSpinnerUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JSpinner}.
|
||||
@@ -56,8 +57,6 @@ import javax.swing.plaf.basic.BasicSpinnerUI;
|
||||
*
|
||||
* <!-- FlatSpinnerUI -->
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.arc int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.arrowType String triangle (default) or chevron
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
@@ -78,8 +77,6 @@ public class FlatSpinnerUI
|
||||
{
|
||||
private Handler handler;
|
||||
|
||||
protected int focusWidth;
|
||||
protected int arc;
|
||||
protected int minimumWidth;
|
||||
protected String arrowType;
|
||||
protected boolean isIntelliJTheme;
|
||||
@@ -103,8 +100,6 @@ public class FlatSpinnerUI
|
||||
|
||||
LookAndFeel.installProperty( spinner, "opaque", false );
|
||||
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
arc = UIManager.getInt( "Component.arc" );
|
||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||
arrowType = UIManager.getString( "Component.arrowType" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
@@ -121,7 +116,7 @@ public class FlatSpinnerUI
|
||||
// scale
|
||||
padding = scale( padding );
|
||||
|
||||
MigLayoutVisualPadding.install( spinner, focusWidth );
|
||||
MigLayoutVisualPadding.install( spinner );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -246,8 +241,11 @@ public class FlatSpinnerUI
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
float arc = FlatUIUtils.getBorderArc( c );
|
||||
|
||||
// fill background if opaque to avoid garbage if user sets opaque to true
|
||||
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
|
||||
if( c.isOpaque() && (focusWidth > 0 || arc > 0) )
|
||||
FlatUIUtils.paintParentBackground( g, c );
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
@@ -255,8 +253,6 @@ public class FlatSpinnerUI
|
||||
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
|
||||
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
|
||||
Component nextButton = getHandler().nextButton;
|
||||
int arrowX = nextButton.getX();
|
||||
int arrowWidth = nextButton.getWidth();
|
||||
@@ -328,8 +324,9 @@ public class FlatSpinnerUI
|
||||
// the arrows width is the same as the inner height so that the arrows area is square
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( spinner, FlatSpinnerUI.this.minimumWidth );
|
||||
int innerHeight = editorSize.height + padding.top + padding.bottom;
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( spinner );
|
||||
return new Dimension(
|
||||
Math.max( insets.left + insets.right + editorSize.width + padding.left + padding.right + innerHeight, scale( minimumWidth + (focusWidth * 2) ) ),
|
||||
Math.max( insets.left + insets.right + editorSize.width + padding.left + padding.right + innerHeight, scale( minimumWidth ) + Math.round( focusWidth * 2 ) ),
|
||||
insets.top + insets.bottom + innerHeight );
|
||||
}
|
||||
|
||||
@@ -398,6 +395,10 @@ public class FlatSpinnerUI
|
||||
case "enabled":
|
||||
updateEditorColors();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
||||
spinner.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicTableUI;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -132,6 +134,12 @@ public class FlatTableUI
|
||||
oldIntercellSpacing = table.getIntercellSpacing();
|
||||
table.setIntercellSpacing( intercellSpacing );
|
||||
}
|
||||
|
||||
// checkbox is non-opaque in FlatLaf and therefore would not paint selection
|
||||
// --> make checkbox renderer opaque (but opaque in Metal or Windows LaF)
|
||||
TableCellRenderer booleanRenderer = table.getDefaultRenderer( Boolean.class );
|
||||
if( booleanRenderer instanceof JCheckBox )
|
||||
((JCheckBox)booleanRenderer).setOpaque( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
@@ -100,25 +99,19 @@ public class FlatTextAreaUI
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getPreferredSize( c ), c );
|
||||
return applyMinimumWidth( c, super.getPreferredSize( c ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getMinimumSize( c ), c );
|
||||
return applyMinimumWidth( c, super.getMinimumSize( c ) );
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
|
||||
private Dimension applyMinimumWidth( JComponent c, Dimension size ) {
|
||||
// do not apply minimum width if JTextArea.columns is set
|
||||
if( c instanceof JTextArea && ((JTextArea)c).getColumns() > 0 )
|
||||
return size;
|
||||
|
||||
// Assume that text area is in a scroll pane (that displays the border)
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
return FlatEditorPaneUI.applyMinimumWidth( c, size, minimumWidth );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Border for various text components (e.g. {@link javax.swing.JTextField}).
|
||||
*
|
||||
* @uiDefault Component.arc int
|
||||
* @uiDefault TextComponent.arc int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -33,7 +32,7 @@ public class FlatTextBorder
|
||||
protected final int arc = UIManager.getInt( "TextComponent.arc" );
|
||||
|
||||
@Override
|
||||
protected float getArc( Component c ) {
|
||||
return scale( (float) arc );
|
||||
protected int getArc( Component c ) {
|
||||
return FlatUIUtils.isRoundRect( c ) ? Short.MAX_VALUE : arc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
*
|
||||
* <!-- FlatTextFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault TextField.placeholderForeground Color
|
||||
@@ -72,8 +70,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
public class FlatTextFieldUI
|
||||
extends BasicTextFieldUI
|
||||
{
|
||||
protected int arc;
|
||||
protected int focusWidth;
|
||||
protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
protected Color placeholderForeground;
|
||||
@@ -89,15 +85,13 @@ public class FlatTextFieldUI
|
||||
super.installDefaults();
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
arc = UIManager.getInt( "TextComponent.arc" );
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
|
||||
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", false );
|
||||
|
||||
MigLayoutVisualPadding.install( getComponent(), focusWidth );
|
||||
MigLayoutVisualPadding.install( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,14 +127,21 @@ public class FlatTextFieldUI
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
propertyChange( getComponent(), e );
|
||||
}
|
||||
|
||||
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
|
||||
getComponent().repaint();
|
||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.PLACEHOLDER_TEXT:
|
||||
case FlatClientProperties.COMPONENT_ROUND_RECT:
|
||||
c.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintSafely( Graphics g ) {
|
||||
paintBackground( g, getComponent(), focusWidth, arc, isIntelliJTheme );
|
||||
paintBackground( g, getComponent(), isIntelliJTheme );
|
||||
paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||
super.paintSafely( g );
|
||||
}
|
||||
@@ -150,7 +151,7 @@ public class FlatTextFieldUI
|
||||
// background is painted elsewhere
|
||||
}
|
||||
|
||||
static void paintBackground( Graphics g, JTextComponent c, int focusWidth, int arc, boolean isIntelliJTheme ) {
|
||||
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme ) {
|
||||
Border border = c.getBorder();
|
||||
|
||||
// do not paint background if:
|
||||
@@ -161,8 +162,11 @@ public class FlatTextFieldUI
|
||||
if( !c.isOpaque() && !(border instanceof FlatBorder) && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
|
||||
return;
|
||||
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
float arc = FlatUIUtils.getBorderArc( c );
|
||||
|
||||
// fill background if opaque to avoid garbage if user sets opaque to true
|
||||
if( c.isOpaque() && focusWidth > 0 )
|
||||
if( c.isOpaque() && (focusWidth > 0 || arc > 0) )
|
||||
FlatUIUtils.paintParentBackground( g, c );
|
||||
|
||||
// paint background
|
||||
@@ -170,16 +174,13 @@ public class FlatTextFieldUI
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
float fFocusWidth = (border instanceof FlatBorder) ? scale( (float) focusWidth ) : 0;
|
||||
float fArc = (border instanceof FlatTextBorder) ? scale( (float) arc ) : 0;
|
||||
|
||||
Color background = c.getBackground();
|
||||
g2.setColor( !(background instanceof UIResource)
|
||||
? background
|
||||
: (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())
|
||||
? FlatUIUtils.getParentBackground( c )
|
||||
: background) );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, fArc );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
@@ -212,28 +213,29 @@ public class FlatTextFieldUI
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getPreferredSize( c ), c );
|
||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getMinimumSize( c ), c );
|
||||
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
|
||||
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
|
||||
// do not apply minimum width if JTextField.columns is set
|
||||
if( c instanceof JTextField && ((JTextField)c).getColumns() > 0 )
|
||||
return size;
|
||||
|
||||
// do not apply minimum width if used in combobox or spinner
|
||||
Container parent = c.getParent();
|
||||
if( parent instanceof JComboBox ||
|
||||
parent instanceof JSpinner ||
|
||||
(parent != null && parent.getParent() instanceof JSpinner) )
|
||||
return size;
|
||||
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
|
||||
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
|
||||
minimumWidth = FlatUIUtils.minimumWidth( c, minimumWidth );
|
||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) + Math.round( focusWidth * 2 ) );
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.JComponent;
|
||||
@@ -85,22 +84,12 @@ public class FlatTextPaneUI
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getPreferredSize( c ) );
|
||||
return FlatEditorPaneUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return applyMinimumWidth( super.getMinimumSize( c ) );
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size ) {
|
||||
// Assume that text area is in a scroll pane (that displays the border)
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
return FlatEditorPaneUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -138,7 +138,7 @@ public class FlatToggleButtonUI
|
||||
case BUTTON_TYPE:
|
||||
if( BUTTON_TYPE_TAB.equals( e.getOldValue() ) || BUTTON_TYPE_TAB.equals( e.getNewValue() ) ) {
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
MigLayoutVisualPadding.install( b, getFocusWidth( b ) );
|
||||
MigLayoutVisualPadding.install( b );
|
||||
b.revalidate();
|
||||
}
|
||||
|
||||
@@ -212,9 +212,4 @@ public class FlatToggleButtonUI
|
||||
|
||||
return super.getForeground( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFocusWidth( JComponent c ) {
|
||||
return isTabButton( c ) ? 0 : super.getFocusWidth( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import javax.swing.JComponent;
|
||||
import javax.swing.JToolTip;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicToolTipUI;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
|
||||
@@ -102,7 +103,7 @@ public class FlatToolTipUI
|
||||
for( String line : lines )
|
||||
width = Math.max( width, SwingUtilities.computeStringWidth( fm, line ) );
|
||||
|
||||
return new Dimension( insets.left + width + insets.right, insets.top + height + insets.bottom );
|
||||
return new Dimension( insets.left + width + insets.right + 6, insets.top + height + insets.bottom );
|
||||
} else
|
||||
return super.getPreferredSize( c );
|
||||
}
|
||||
@@ -118,8 +119,8 @@ public class FlatToolTipUI
|
||||
|
||||
List<String> lines = StringUtils.split( ((JToolTip)c).getTipText(), '\n' );
|
||||
|
||||
int x = insets.left;
|
||||
int x2 = c.getWidth() - insets.right;
|
||||
int x = insets.left + 3;
|
||||
int x2 = c.getWidth() - insets.right - 3;
|
||||
int y = insets.top - fm.getDescent();
|
||||
int lineHeight = fm.getHeight();
|
||||
JComponent comp = ((JToolTip)c).getComponent();
|
||||
@@ -134,6 +135,6 @@ public class FlatToolTipUI
|
||||
|
||||
private boolean isMultiLine( JComponent c ) {
|
||||
String text = ((JToolTip)c).getTipText();
|
||||
return c.getClientProperty( "html" ) == null && text != null && text.indexOf( '\n' ) >= 0;
|
||||
return c.getClientProperty( BasicHTML.propertyKey ) == null && text != null && text.indexOf( '\n' ) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,9 +39,11 @@ import java.util.function.Consumer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.JavaCompatibility;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -141,6 +143,31 @@ public class FlatUIUtils
|
||||
return (KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() == c);
|
||||
}
|
||||
|
||||
public static boolean isRoundRect( Component c ) {
|
||||
return c instanceof JComponent && FlatClientProperties.clientPropertyBoolean(
|
||||
(JComponent) c, FlatClientProperties.COMPONENT_ROUND_RECT, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaled thickness of the outer focus border for the given component.
|
||||
*/
|
||||
public static float getBorderFocusWidth( JComponent c ) {
|
||||
Border border = c.getBorder();
|
||||
return (border instanceof FlatBorder)
|
||||
? UIScale.scale( (float) ((FlatBorder)border).getFocusWidth( c ) )
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaled arc diameter of the border for the given component.
|
||||
*/
|
||||
public static float getBorderArc( JComponent c ) {
|
||||
Border border = c.getBorder();
|
||||
return (border instanceof FlatBorder)
|
||||
? UIScale.scale( (float) ((FlatBorder)border).getArc( c ) )
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets rendering hints used for painting.
|
||||
*/
|
||||
@@ -194,14 +221,9 @@ public class FlatUIUtils
|
||||
if( arc > 0 && arc < UIScale.scale( 10 ) )
|
||||
outerArc -= UIScale.scale( 2f );
|
||||
|
||||
if( outerArc < 0 )
|
||||
outerArc = 0;
|
||||
if( innerArc < 0 )
|
||||
innerArc = 0;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new RoundRectangle2D.Float( x, y, width, height, outerArc, outerArc ), false );
|
||||
path.append( new RoundRectangle2D.Float( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerArc, innerArc ), false );
|
||||
path.append( createComponentRectangle( x, y, width, height, outerArc ), false );
|
||||
path.append( createComponentRectangle( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerArc ), false );
|
||||
g.fill( path );
|
||||
}
|
||||
|
||||
@@ -235,19 +257,16 @@ public class FlatUIUtils
|
||||
private static void paintComponentBorderImpl( Graphics2D g, int x, int y, int width, int height,
|
||||
float focusWidth, float lineWidth, float arc )
|
||||
{
|
||||
float x1 = x + focusWidth;
|
||||
float y1 = y + focusWidth;
|
||||
float width1 = width - focusWidth * 2;
|
||||
float height1 = height - focusWidth * 2;
|
||||
float arc2 = arc - (lineWidth * 2);
|
||||
|
||||
if( arc < 0 )
|
||||
arc = 0;
|
||||
if( arc2 < 0 )
|
||||
arc2 = 0;
|
||||
|
||||
RoundRectangle2D.Float r1 = new RoundRectangle2D.Float(
|
||||
x + focusWidth, y + focusWidth,
|
||||
width - focusWidth * 2, height - focusWidth * 2, arc, arc );
|
||||
RoundRectangle2D.Float r2 = new RoundRectangle2D.Float(
|
||||
r1.x + lineWidth, r1.y + lineWidth,
|
||||
r1.width - lineWidth * 2, r1.height - lineWidth * 2, arc2, arc2 );
|
||||
Shape r1 = createComponentRectangle( x1, y1, width1, height1, arc );
|
||||
Shape r2 = createComponentRectangle(
|
||||
x1 + lineWidth, y1 + lineWidth,
|
||||
width1 - lineWidth * 2, height1 - lineWidth * 2, arc2 );
|
||||
|
||||
Path2D border = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
border.append( r1, false );
|
||||
@@ -285,12 +304,21 @@ public class FlatUIUtils
|
||||
private static void paintComponentBackgroundImpl( Graphics2D g, int x, int y, int width, int height,
|
||||
float focusWidth, float arc )
|
||||
{
|
||||
if( arc < 0 )
|
||||
arc = 0;
|
||||
|
||||
g.fill( new RoundRectangle2D.Float(
|
||||
g.fill( createComponentRectangle(
|
||||
x + focusWidth, y + focusWidth,
|
||||
width - focusWidth * 2, height - focusWidth * 2, arc, arc ) );
|
||||
width - focusWidth * 2, height - focusWidth * 2, arc ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a (rounded) rectangle used to paint components (border, background, etc).
|
||||
* The given arc diameter is limited to min(width,height).
|
||||
*/
|
||||
public static Shape createComponentRectangle( float x, float y, float w, float h, float arc ) {
|
||||
if( arc <= 0 )
|
||||
return new Rectangle2D.Float( x, y, w, h );
|
||||
|
||||
arc = Math.min( arc, Math.min( w, h ) );
|
||||
return new RoundRectangle2D.Float( x, y, w, h, arc, arc );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,14 +387,12 @@ public class FlatUIUtils
|
||||
if( arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0 && arcBottomRight <= 0 )
|
||||
return new Rectangle2D.Float( x, y, width, height );
|
||||
|
||||
if( arcTopLeft < 0 )
|
||||
arcTopLeft = 0;
|
||||
if( arcTopRight < 0 )
|
||||
arcTopRight = 0;
|
||||
if( arcBottomLeft < 0 )
|
||||
arcBottomLeft = 0;
|
||||
if( arcBottomRight < 0 )
|
||||
arcBottomRight = 0;
|
||||
// limit arcs to min(width,height)
|
||||
float maxArc = Math.min( width, height ) / 2;
|
||||
arcTopLeft = (arcTopLeft > 0) ? Math.min( arcTopLeft, maxArc ) : 0;
|
||||
arcTopRight = (arcTopRight > 0) ? Math.min( arcTopRight, maxArc ) : 0;
|
||||
arcBottomLeft = (arcBottomLeft > 0) ? Math.min( arcBottomLeft, maxArc ) : 0;
|
||||
arcBottomRight = (arcBottomRight > 0) ? Math.min( arcBottomRight, maxArc ) : 0;
|
||||
|
||||
float x2 = x + width;
|
||||
float y2 = y + height;
|
||||
@@ -427,6 +453,23 @@ public class FlatUIUtils
|
||||
public static void drawStringUnderlineCharAt( JComponent c, Graphics g,
|
||||
String text, int underlinedIndex, int x, int y )
|
||||
{
|
||||
// scale underline height if necessary
|
||||
if( underlinedIndex >= 0 && UIScale.getUserScaleFactor() > 1 ) {
|
||||
g = new Graphics2DProxy( (Graphics2D) g ) {
|
||||
@Override
|
||||
public void fillRect( int x, int y, int width, int height ) {
|
||||
if( height == 1 ) {
|
||||
// scale height and correct y position
|
||||
// (using 0.9f so that underline height is 1 at scale factor 1.5x)
|
||||
height = Math.round( UIScale.scale( 0.9f ) );
|
||||
y += height - 1;
|
||||
}
|
||||
|
||||
super.fillRect( x, y, width, height );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.Insets;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.border.Border;
|
||||
|
||||
/**
|
||||
* Support for MigLayout visual paddings.
|
||||
@@ -69,14 +70,17 @@ public class MigLayoutVisualPadding
|
||||
/**
|
||||
* Convenience method that checks whether component border is a FlatBorder.
|
||||
*/
|
||||
public static void install( JComponent c, int focusWidth ) {
|
||||
public static void install( JComponent c ) {
|
||||
if( !migLayoutAvailable )
|
||||
return;
|
||||
|
||||
install( c, c2 -> {
|
||||
return (c2.getBorder() instanceof FlatBorder)
|
||||
? new Insets( focusWidth, focusWidth, focusWidth, focusWidth )
|
||||
: null;
|
||||
Border border = c2.getBorder();
|
||||
if( border instanceof FlatBorder ) {
|
||||
int focusWidth = ((FlatBorder)border).getFocusWidth( c2 );
|
||||
return new Insets( focusWidth, focusWidth, focusWidth, focusWidth );
|
||||
} else
|
||||
return null;
|
||||
}, "border" );
|
||||
}
|
||||
|
||||
|
||||
@@ -49,20 +49,26 @@ public class ColorFunctions
|
||||
void apply( float[] hsl );
|
||||
}
|
||||
|
||||
//---- class Lighten ------------------------------------------------------
|
||||
//---- class HSLIncreaseDecrease ------------------------------------------
|
||||
|
||||
/**
|
||||
* Increase the lightness of a color in the HSL color space by an absolute
|
||||
* or relative amount.
|
||||
* Increase or decrease hue, saturation or luminance of a color in the HSL color space
|
||||
* by an absolute or relative amount.
|
||||
*/
|
||||
public static class Lighten
|
||||
public static class HSLIncreaseDecrease
|
||||
implements ColorFunction
|
||||
{
|
||||
private final float amount;
|
||||
private final boolean relative;
|
||||
private final boolean autoInverse;
|
||||
public final int hslIndex;
|
||||
public final boolean increase;
|
||||
public final float amount;
|
||||
public final boolean relative;
|
||||
public final boolean autoInverse;
|
||||
|
||||
public Lighten( float amount, boolean relative, boolean autoInverse ) {
|
||||
public HSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||
float amount, boolean relative, boolean autoInverse )
|
||||
{
|
||||
this.hslIndex = hslIndex;
|
||||
this.increase = increase;
|
||||
this.amount = amount;
|
||||
this.relative = relative;
|
||||
this.autoInverse = autoInverse;
|
||||
@@ -70,33 +76,17 @@ public class ColorFunctions
|
||||
|
||||
@Override
|
||||
public void apply( float[] hsl ) {
|
||||
float amount2 = autoInverse && shouldInverse( hsl ) ? -amount : amount;
|
||||
hsl[2] = clamp( relative
|
||||
? (hsl[2] * ((100 + amount2) / 100))
|
||||
: (hsl[2] + amount2) );
|
||||
float amount2 = increase ? amount : -amount;
|
||||
amount2 = autoInverse && shouldInverse( hsl ) ? -amount2 : amount2;
|
||||
hsl[hslIndex] = clamp( relative
|
||||
? (hsl[hslIndex] * ((100 + amount2) / 100))
|
||||
: (hsl[hslIndex] + amount2) );
|
||||
}
|
||||
|
||||
protected boolean shouldInverse( float[] hsl ) {
|
||||
return hsl[2] >= 50;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class Darken -------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Decrease the lightness of a color in the HSL color space by an absolute
|
||||
* or relative amount.
|
||||
*/
|
||||
public static class Darken
|
||||
extends Lighten
|
||||
{
|
||||
public Darken( float amount, boolean relative, boolean autoInverse ) {
|
||||
super( -amount, relative, autoInverse );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldInverse( float[] hsl ) {
|
||||
return hsl[2] < 50;
|
||||
return increase
|
||||
? hsl[hslIndex] >= 50
|
||||
: hsl[hslIndex] < 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,16 @@ public class DerivedColor
|
||||
{
|
||||
private final ColorFunction[] functions;
|
||||
|
||||
public DerivedColor( ColorFunction... functions ) {
|
||||
super( Color.red );
|
||||
public DerivedColor( Color defaultColor, ColorFunction... functions ) {
|
||||
super( (defaultColor != null) ? defaultColor : Color.red );
|
||||
this.functions = functions;
|
||||
}
|
||||
|
||||
public Color derive( Color baseColor ) {
|
||||
return ColorFunctions.applyFunctions( baseColor, functions );
|
||||
}
|
||||
|
||||
public ColorFunction[] getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.RenderingHints.Key;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A proxy for {@link Graphics2D}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class Graphics2DProxy
|
||||
extends Graphics2D
|
||||
{
|
||||
private final Graphics2D delegate;
|
||||
|
||||
public Graphics2DProxy( Graphics2D delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return delegate.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create( int x, int y, int width, int height ) {
|
||||
return delegate.create( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return delegate.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor( Color c ) {
|
||||
delegate.setColor( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaintMode() {
|
||||
delegate.setPaintMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXORMode( Color c1 ) {
|
||||
delegate.setXORMode( c1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font getFont() {
|
||||
return delegate.getFont();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont( Font font ) {
|
||||
delegate.setFont( font );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics() {
|
||||
return delegate.getFontMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics( Font f ) {
|
||||
return delegate.getFontMetrics( f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds() {
|
||||
return delegate.getClipBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipRect( int x, int y, int width, int height ) {
|
||||
delegate.clipRect( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip( int x, int y, int width, int height ) {
|
||||
delegate.setClip( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getClip() {
|
||||
return delegate.getClip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip( Shape clip ) {
|
||||
delegate.setClip( clip );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyArea( int x, int y, int width, int height, int dx, int dy ) {
|
||||
delegate.copyArea( x, y, width, height, dx, dy );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine( int x1, int y1, int x2, int y2 ) {
|
||||
delegate.drawLine( x1, y1, x2, y2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect( int x, int y, int width, int height ) {
|
||||
delegate.fillRect( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect( int x, int y, int width, int height ) {
|
||||
delegate.drawRect( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRect( int x, int y, int width, int height ) {
|
||||
delegate.clearRect( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect( int x, int y, int width, int height, int arcWidth, int arcHeight ) {
|
||||
delegate.drawRoundRect( x, y, width, height, arcWidth, arcHeight );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRoundRect( int x, int y, int width, int height, int arcWidth, int arcHeight ) {
|
||||
delegate.fillRoundRect( x, y, width, height, arcWidth, arcHeight );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval( int x, int y, int width, int height ) {
|
||||
delegate.drawOval( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillOval( int x, int y, int width, int height ) {
|
||||
delegate.fillOval( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc( int x, int y, int width, int height, int startAngle, int arcAngle ) {
|
||||
delegate.drawArc( x, y, width, height, startAngle, arcAngle );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillArc( int x, int y, int width, int height, int startAngle, int arcAngle ) {
|
||||
delegate.fillArc( x, y, width, height, startAngle, arcAngle );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolyline( int[] xPoints, int[] yPoints, int nPoints ) {
|
||||
delegate.drawPolyline( xPoints, yPoints, nPoints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolygon( int[] xPoints, int[] yPoints, int nPoints ) {
|
||||
delegate.drawPolygon( xPoints, yPoints, nPoints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolygon( Polygon p ) {
|
||||
delegate.drawPolygon( p );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon( int[] xPoints, int[] yPoints, int nPoints ) {
|
||||
delegate.fillPolygon( xPoints, yPoints, nPoints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon( Polygon p ) {
|
||||
delegate.fillPolygon( p );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawChars( char[] data, int offset, int length, int x, int y ) {
|
||||
delegate.drawChars( data, offset, length, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBytes( byte[] data, int offset, int length, int x, int y ) {
|
||||
delegate.drawBytes( data, offset, length, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int x, int y, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, x, y, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int x, int y, int width, int height, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, x, y, width, height, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int x, int y, Color bgcolor, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, x, y, bgcolor, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, x, y, width, height, bgcolor, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer ) {
|
||||
return delegate.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
delegate.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() {
|
||||
delegate.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings( "deprecation" )
|
||||
@Override
|
||||
public Rectangle getClipRect() {
|
||||
return delegate.getClipRect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hitClip( int x, int y, int width, int height ) {
|
||||
return delegate.hitClip( x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds( Rectangle r ) {
|
||||
return delegate.getClipBounds( r );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw3DRect( int x, int y, int width, int height, boolean raised ) {
|
||||
delegate.draw3DRect( x, y, width, height, raised );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill3DRect( int x, int y, int width, int height, boolean raised ) {
|
||||
delegate.fill3DRect( x, y, width, height, raised );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw( Shape s ) {
|
||||
delegate.draw( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage( Image img, AffineTransform xform, ImageObserver obs ) {
|
||||
return delegate.drawImage( img, xform, obs );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawImage( BufferedImage img, BufferedImageOp op, int x, int y ) {
|
||||
delegate.drawImage( img, op, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderedImage( RenderedImage img, AffineTransform xform ) {
|
||||
delegate.drawRenderedImage( img, xform );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderableImage( RenderableImage img, AffineTransform xform ) {
|
||||
delegate.drawRenderableImage( img, xform );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( String str, int x, int y ) {
|
||||
delegate.drawString( str, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( String str, float x, float y ) {
|
||||
delegate.drawString( str, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( AttributedCharacterIterator iterator, int x, int y ) {
|
||||
delegate.drawString( iterator, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString( AttributedCharacterIterator iterator, float x, float y ) {
|
||||
delegate.drawString( iterator, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlyphVector( GlyphVector g, float x, float y ) {
|
||||
delegate.drawGlyphVector( g, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill( Shape s ) {
|
||||
delegate.fill( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hit( Rectangle rect, Shape s, boolean onStroke ) {
|
||||
return delegate.hit( rect, s, onStroke );
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return delegate.getDeviceConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComposite( Composite comp ) {
|
||||
delegate.setComposite( comp );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaint( Paint paint ) {
|
||||
delegate.setPaint( paint );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStroke( Stroke s ) {
|
||||
delegate.setStroke( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHint( Key hintKey, Object hintValue ) {
|
||||
delegate.setRenderingHint( hintKey, hintValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderingHint( Key hintKey ) {
|
||||
return delegate.getRenderingHint( hintKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHints( Map<?, ?> hints ) {
|
||||
delegate.setRenderingHints( hints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRenderingHints( Map<?, ?> hints ) {
|
||||
delegate.addRenderingHints( hints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return delegate.getRenderingHints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate( int x, int y ) {
|
||||
delegate.translate( x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate( double tx, double ty ) {
|
||||
delegate.translate( tx, ty );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate( double theta ) {
|
||||
delegate.rotate( theta );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate( double theta, double x, double y ) {
|
||||
delegate.rotate( theta, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scale( double sx, double sy ) {
|
||||
delegate.scale( sx, sy );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shear( double shx, double shy ) {
|
||||
delegate.shear( shx, shy );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform( AffineTransform Tx ) {
|
||||
delegate.transform( Tx );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform( AffineTransform Tx ) {
|
||||
delegate.setTransform( Tx );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getTransform() {
|
||||
return delegate.getTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint() {
|
||||
return delegate.getPaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite getComposite() {
|
||||
return delegate.getComposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground( Color color ) {
|
||||
delegate.setBackground( color );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
return delegate.getBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stroke getStroke() {
|
||||
return delegate.getStroke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clip( Shape s ) {
|
||||
delegate.clip( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontRenderContext getFontRenderContext() {
|
||||
return delegate.getFontRenderContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2000-2020 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.
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.image.RGBImageFilter;
|
||||
|
||||
// based on https://github.com/JetBrains/intellij-community/blob/3840eab54746f5c4f301bb3ac78f00a980b5fd6e/platform/util/ui/src/com/intellij/util/ui/UIUtil.java#L253-L347
|
||||
|
||||
/**
|
||||
* An image filter that turns an image into a grayscale image.
|
||||
* Used for icons in disabled buttons and labels.
|
||||
*/
|
||||
public class GrayFilter
|
||||
extends RGBImageFilter
|
||||
{
|
||||
private final float brightness;
|
||||
private final float contrast;
|
||||
private final int alpha;
|
||||
|
||||
private final int origContrast;
|
||||
private final int origBrightness;
|
||||
|
||||
public static GrayFilter createDisabledIconFilter( boolean dark ) {
|
||||
return dark
|
||||
? new GrayFilter( -20, -70, 100 )
|
||||
: new GrayFilter( 25, -25, 100 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param brightness in range [-100..100] where 0 has no effect
|
||||
* @param contrast in range [-100..100] where 0 has no effect
|
||||
* @param alpha in range [0..100] where 0 is transparent, 100 has no effect
|
||||
*/
|
||||
public GrayFilter( int brightness, int contrast, int alpha ) {
|
||||
this.origBrightness = Math.max( -100, Math.min( 100, brightness ) );
|
||||
this.origContrast = Math.max( -100, Math.min( 100, contrast ) );
|
||||
this.alpha = Math.max( 0, Math.min( 100, alpha ) );
|
||||
|
||||
this.brightness = (float) (Math.pow( origBrightness, 3 ) / (100f * 100f)); // cubic in [0..100]
|
||||
this.contrast = origContrast / 100f;
|
||||
|
||||
canFilterIndexColorModel = true;
|
||||
}
|
||||
|
||||
public GrayFilter() {
|
||||
this( 0, 0, 100 );
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return origBrightness;
|
||||
}
|
||||
|
||||
public int getContrast() {
|
||||
return origContrast;
|
||||
}
|
||||
|
||||
public int getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int filterRGB( int x, int y, int rgb ) {
|
||||
// use NTSC conversion formula
|
||||
int gray = (int)(
|
||||
0.30 * (rgb >> 16 & 0xff) +
|
||||
0.59 * (rgb >> 8 & 0xff) +
|
||||
0.11 * (rgb & 0xff));
|
||||
|
||||
if( brightness >= 0 )
|
||||
gray = (int) ((gray + brightness * 255) / (1 + brightness));
|
||||
else
|
||||
gray = (int) (gray / (1 - brightness));
|
||||
|
||||
if( contrast >= 0 ) {
|
||||
if( gray >= 127 )
|
||||
gray = (int) (gray + (255 - gray) * contrast);
|
||||
else
|
||||
gray = (int) (gray - gray * contrast);
|
||||
} else
|
||||
gray = (int) (127 + (gray - 127) * (contrast + 1));
|
||||
|
||||
int a = (alpha != 100)
|
||||
? (((rgb >> 24) & 0xff) * alpha / 100) << 24
|
||||
: (rgb & 0xff000000);
|
||||
|
||||
return a | (gray << 16) | (gray << 8) | gray;
|
||||
}
|
||||
}
|
||||
@@ -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.util;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Support for multi-resolution images available since Java 9.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class MultiResolutionImageSupport
|
||||
{
|
||||
public static boolean isAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isMultiResolutionImage( Image image ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Image create( int baseImageIndex, Image... resolutionVariants ) {
|
||||
return resolutionVariants[baseImageIndex];
|
||||
}
|
||||
|
||||
public static Image map( Image image, Function<Image, Image> mapper ) {
|
||||
return mapper.apply( image );
|
||||
}
|
||||
|
||||
public static Image getResolutionVariant( Image image, int destImageWidth, int destImageHeight ) {
|
||||
return image;
|
||||
}
|
||||
|
||||
public static List<Image> getResolutionVariants( Image image ) {
|
||||
return Collections.singletonList( image );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
/**
|
||||
* Scales the given image icon using the system and user scale factors and
|
||||
* paints the icon at system scale factor 1x. This gives best scaling quality.
|
||||
* If the given image icon supports multiple resolutions, the best resolution
|
||||
* variant is used. The last scaled image is cached for faster repainting.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class ScaledImageIcon
|
||||
implements Icon
|
||||
{
|
||||
private final ImageIcon imageIcon;
|
||||
|
||||
private double lastSystemScaleFactor;
|
||||
private float lastUserScaleFactor;
|
||||
private Image lastImage;
|
||||
|
||||
public ScaledImageIcon( ImageIcon imageIcon ) {
|
||||
this.imageIcon = imageIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return UIScale.scale( imageIcon.getIconWidth() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return UIScale.scale( imageIcon.getIconHeight() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||
/*debug
|
||||
g.setColor( Color.red );
|
||||
g.drawRect( x, y, getIconWidth(), getIconHeight() );
|
||||
debug*/
|
||||
|
||||
// scale factor
|
||||
double systemScaleFactor = UIScale.getSystemScaleFactor( (Graphics2D) g );
|
||||
float userScaleFactor = UIScale.getUserScaleFactor();
|
||||
double scaleFactor = systemScaleFactor * userScaleFactor;
|
||||
|
||||
// paint input image icon if not necessary to scale
|
||||
if( scaleFactor == 1 ) {
|
||||
imageIcon.paintIcon( c, g, x, y );
|
||||
return;
|
||||
}
|
||||
|
||||
// paint cached scaled icon
|
||||
if( systemScaleFactor == lastSystemScaleFactor &&
|
||||
userScaleFactor == lastUserScaleFactor &&
|
||||
lastImage != null )
|
||||
{
|
||||
paintLastImage( g, x, y );
|
||||
return;
|
||||
}
|
||||
|
||||
// destination image size
|
||||
int destImageWidth = (int) Math.round( imageIcon.getIconWidth() * scaleFactor );
|
||||
int destImageHeight = (int) Math.round( imageIcon.getIconHeight() * scaleFactor );
|
||||
|
||||
// get resolution variant of image if it is a multi-resolution image
|
||||
Image image = MultiResolutionImageSupport.getResolutionVariant(
|
||||
imageIcon.getImage(), destImageWidth, destImageHeight );
|
||||
|
||||
// size of image
|
||||
int imageWidth = image.getWidth( null );
|
||||
int imageHeight = image.getHeight( null );
|
||||
|
||||
// scale image if necessary to destination size
|
||||
if( imageWidth != destImageWidth || imageHeight != destImageHeight ) {
|
||||
// determine scaling method; default is "quality"
|
||||
Object scalingInterpolation = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
|
||||
float imageScaleFactor = (float) destImageWidth / (float) imageWidth;
|
||||
if( ((int) imageScaleFactor) == imageScaleFactor &&
|
||||
imageScaleFactor > 1f &&
|
||||
imageWidth <= 16 &&
|
||||
imageHeight <= 16 )
|
||||
{
|
||||
// use "speed" scaling for small icons if the scale factor is an integer
|
||||
// to avoid blurred icons
|
||||
scalingInterpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
|
||||
}
|
||||
|
||||
// scale image
|
||||
BufferedImage bufferedImage = image2bufferedImage( image );
|
||||
image = scaleImage( bufferedImage, destImageWidth, destImageHeight, scalingInterpolation );
|
||||
}
|
||||
|
||||
// cache image
|
||||
lastSystemScaleFactor = systemScaleFactor;
|
||||
lastUserScaleFactor = userScaleFactor;
|
||||
lastImage = image;
|
||||
|
||||
// paint image
|
||||
paintLastImage( g, x, y );
|
||||
}
|
||||
|
||||
private void paintLastImage( Graphics g, int x, int y ) {
|
||||
if( lastSystemScaleFactor > 1 ) {
|
||||
HiDPIUtils.paintAtScale1x( (Graphics2D) g, x, y, 100, 100, // width and height are not used
|
||||
(g2, x2, y2, width2, height2, scaleFactor2) -> {
|
||||
g2.drawImage( lastImage, x2, y2, null );
|
||||
} );
|
||||
} else
|
||||
g.drawImage( lastImage, x, y, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the given image to the target dimensions.
|
||||
*
|
||||
* This is the same what imgscalr library (https://github.com/rkalla/imgscalr)
|
||||
* would do when invoking Scalr.resize().
|
||||
*/
|
||||
private BufferedImage scaleImage( BufferedImage image, int targetWidth, int targetHeight,
|
||||
Object scalingInterpolation )
|
||||
{
|
||||
BufferedImage bufferedImage = new BufferedImage( targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB );
|
||||
Graphics2D g = bufferedImage.createGraphics();
|
||||
try {
|
||||
g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, scalingInterpolation );
|
||||
g.drawImage( image, 0, 0, targetWidth, targetHeight, null );
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
return bufferedImage;
|
||||
|
||||
}
|
||||
|
||||
private BufferedImage image2bufferedImage( Image image ) {
|
||||
if( image instanceof BufferedImage )
|
||||
return (BufferedImage) image;
|
||||
|
||||
BufferedImage bufferedImage = new BufferedImage( image.getWidth( null ),
|
||||
image.getHeight( null ), BufferedImage.TYPE_INT_ARGB );
|
||||
Graphics2D g = bufferedImage.createGraphics();
|
||||
try {
|
||||
g.drawImage( image, 0, 0, null );
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
return bufferedImage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.AbstractMultiResolutionImage;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
/**
|
||||
* Support for multi-resolution images available since Java 9.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class MultiResolutionImageSupport
|
||||
{
|
||||
public static boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isMultiResolutionImage( Image image ) {
|
||||
return image instanceof MultiResolutionImage;
|
||||
}
|
||||
|
||||
public static Image create( int baseImageIndex, Image... resolutionVariants ) {
|
||||
return new BaseMultiResolutionImage( baseImageIndex, resolutionVariants );
|
||||
}
|
||||
|
||||
public static Image map( Image image, Function<Image, Image> mapper ) {
|
||||
return image instanceof MultiResolutionImage
|
||||
? new MappedMultiResolutionImage( image, mapper )
|
||||
: mapper.apply( image );
|
||||
}
|
||||
|
||||
public static Image getResolutionVariant( Image image, int destImageWidth, int destImageHeight ) {
|
||||
return (image instanceof MultiResolutionImage)
|
||||
? ((MultiResolutionImage)image).getResolutionVariant( destImageWidth, destImageHeight )
|
||||
: image;
|
||||
}
|
||||
|
||||
public static List<Image> getResolutionVariants( Image image ) {
|
||||
return (image instanceof MultiResolutionImage)
|
||||
? ((MultiResolutionImage)image).getResolutionVariants()
|
||||
: Collections.singletonList( image );
|
||||
}
|
||||
|
||||
//---- class MappedMultiResolutionImage -----------------------------------
|
||||
|
||||
private static class MappedMultiResolutionImage
|
||||
extends AbstractMultiResolutionImage
|
||||
{
|
||||
private final Image mrImage;
|
||||
private final Function<Image, Image> mapper;
|
||||
private final IdentityHashMap<Image, Image> cache = new IdentityHashMap<>();
|
||||
|
||||
MappedMultiResolutionImage( Image mrImage, Function<Image, Image> mapper ) {
|
||||
assert mrImage instanceof MultiResolutionImage;
|
||||
|
||||
this.mrImage = mrImage;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant( double destImageWidth, double destImageHeight ) {
|
||||
Image variant = ((MultiResolutionImage)mrImage).getResolutionVariant( destImageWidth, destImageHeight );
|
||||
return mapAndCacheImage( variant );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
List<Image> variants = ((MultiResolutionImage)mrImage).getResolutionVariants();
|
||||
List<Image> mappedVariants = new ArrayList<>();
|
||||
for( Image image : variants )
|
||||
mappedVariants.add( mapAndCacheImage( image ) );
|
||||
return mappedVariants;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Image getBaseImage() {
|
||||
return mapAndCacheImage( mrImage );
|
||||
}
|
||||
|
||||
private Image mapAndCacheImage( Image image ) {
|
||||
return cache.computeIfAbsent( image, img -> {
|
||||
return new ImageIcon( mapper.apply( img ) ).getImage();
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,7 @@ module com.formdev.flatlaf {
|
||||
exports com.formdev.flatlaf.ui;
|
||||
exports com.formdev.flatlaf.util;
|
||||
|
||||
opens com.formdev.flatlaf.resources;
|
||||
|
||||
uses com.formdev.flatlaf.FlatDefaultsAddon;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ Button.default.boldText=true
|
||||
|
||||
Component.focusWidth=2
|
||||
Component.innerFocusWidth=0
|
||||
Component.innerOutlineWidth=0
|
||||
Component.arrowType=triangle
|
||||
|
||||
|
||||
|
||||
@@ -29,13 +29,12 @@
|
||||
@disabledText=#777777
|
||||
@textComponentBackground=#45494A
|
||||
@menuBackground=darken(@background,5%)
|
||||
@menuHoverBackground=lighten(@menuBackground,10%)
|
||||
@menuCheckBackground=lighten(@menuBackground,10%)
|
||||
@menuCheckHoverBackground=lighten(@menuBackground,20%)
|
||||
@cellFocusColor=#000000
|
||||
@icon=#adadad
|
||||
|
||||
# Button
|
||||
@buttonHoverBackground=lighten(3%,autoInverse)
|
||||
@buttonPressedBackground=lighten(6%,autoInverse)
|
||||
|
||||
# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors)
|
||||
@dropCellBackground=darken(List.selectionBackground,10%,lazy)
|
||||
@dropCellForeground=lazy(List.selectionForeground)
|
||||
@@ -57,7 +56,7 @@
|
||||
*.disabledBackground=@background
|
||||
*.disabledForeground=@disabledText
|
||||
*.disabledText=@disabledText
|
||||
*.acceleratorForeground=#bbbbbb
|
||||
*.acceleratorForeground=darken(@foreground,15%)
|
||||
*.acceleratorSelectionForeground=@selectionForeground
|
||||
|
||||
|
||||
@@ -73,8 +72,8 @@ controlDkShadow=lighten($controlShadow,10%)
|
||||
#---- Button ----
|
||||
|
||||
Button.background=#4c5052
|
||||
Button.hoverBackground=@buttonHoverBackground
|
||||
Button.pressedBackground=@buttonPressedBackground
|
||||
Button.hoverBackground=lighten($Button.background,3%,derived autoInverse)
|
||||
Button.pressedBackground=lighten($Button.background,6%,derived autoInverse)
|
||||
|
||||
Button.borderColor=#5e6060
|
||||
Button.disabledBorderColor=#5e6060
|
||||
@@ -83,16 +82,16 @@ Button.hoverBorderColor=$Button.focusedBorderColor
|
||||
|
||||
Button.default.background=#365880
|
||||
Button.default.foreground=#bbbbbb
|
||||
Button.default.hoverBackground=@buttonHoverBackground
|
||||
Button.default.pressedBackground=@buttonPressedBackground
|
||||
Button.default.hoverBackground=lighten($Button.default.background,3%,derived autoInverse)
|
||||
Button.default.pressedBackground=lighten($Button.default.background,6%,derived autoInverse)
|
||||
Button.default.borderColor=#4c708c
|
||||
Button.default.hoverBorderColor=#537699
|
||||
Button.default.focusedBorderColor=#537699
|
||||
Button.default.focusColor=#43688c
|
||||
Button.default.boldText=true
|
||||
|
||||
Button.toolbar.hoverBackground=#4c5052
|
||||
Button.toolbar.pressedBackground=#555a5d
|
||||
Button.toolbar.hoverBackground=lighten($Button.background,1%,derived autoInverse)
|
||||
Button.toolbar.pressedBackground=lighten($Button.background,4%,derived autoInverse)
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
@@ -105,8 +104,8 @@ CheckBox.icon.hoverBorderColor=$CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.selectedFocusedBorderColor=#466D94
|
||||
CheckBox.icon.background=#43494A
|
||||
CheckBox.icon.disabledBackground=@background
|
||||
CheckBox.icon.hoverBackground=@buttonHoverBackground
|
||||
CheckBox.icon.pressedBackground=@buttonPressedBackground
|
||||
CheckBox.icon.hoverBackground=lighten($CheckBox.icon.background,3%,derived autoInverse)
|
||||
CheckBox.icon.pressedBackground=lighten($CheckBox.icon.background,6%,derived autoInverse)
|
||||
CheckBox.icon.selectedBackground=#43494A
|
||||
CheckBox.icon.checkmarkColor=#A7A7A7
|
||||
CheckBox.icon.disabledCheckmarkColor=#606060
|
||||
@@ -129,6 +128,13 @@ Component.disabledBorderColor=#646464
|
||||
Component.focusedBorderColor=#466d94
|
||||
Component.focusColor=#3d6185
|
||||
Component.linkColor=#589df6
|
||||
Component.grayFilter=-20,-70,100
|
||||
|
||||
Component.error.borderColor=desaturate($Component.error.focusedBorderColor,25%)
|
||||
Component.error.focusedBorderColor=#8b3c3c
|
||||
Component.warning.borderColor=darken(desaturate($Component.warning.focusedBorderColor,20%),10%)
|
||||
Component.warning.focusedBorderColor=#ac7920
|
||||
Component.custom.borderColor=desaturate(#f00,50%,relative derived)
|
||||
|
||||
|
||||
#---- Desktop ----
|
||||
@@ -148,16 +154,19 @@ InternalFrame.activeTitleForeground=@foreground
|
||||
InternalFrame.inactiveTitleBackground=darken(@background,5%)
|
||||
InternalFrame.inactiveTitleForeground=@disabledText
|
||||
|
||||
InternalFrame.activeBorderColor=lighten($Component.borderColor,10%)
|
||||
InternalFrame.inactiveBorderColor=$Component.borderColor
|
||||
InternalFrame.activeBorderColor=darken(@background,7%)
|
||||
InternalFrame.inactiveBorderColor=darken(@background,3%)
|
||||
|
||||
InternalFrame.buttonHoverBackground=lighten(10%,autoInverse)
|
||||
InternalFrame.buttonPressedBackground=lighten(20%,autoInverse)
|
||||
InternalFrame.buttonHoverBackground=lighten($InternalFrame.activeTitleBackground,10%,derived autoInverse)
|
||||
InternalFrame.buttonPressedBackground=lighten($InternalFrame.activeTitleBackground,20%,derived autoInverse)
|
||||
InternalFrame.closeHoverBackground=lazy(Actions.Red)
|
||||
InternalFrame.closePressedBackground=darken(Actions.Red,10%,lazy)
|
||||
InternalFrame.closeHoverForeground=#fff
|
||||
InternalFrame.closePressedForeground=#fff
|
||||
|
||||
InternalFrame.activeDropShadowOpacity=0.5
|
||||
InternalFrame.inactiveDropShadowOpacity=0.75
|
||||
|
||||
|
||||
#---- List ----
|
||||
|
||||
@@ -173,7 +182,7 @@ Menu.icon.disabledArrowColor=#606060
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.borderColor=#515151
|
||||
MenuBar.hoverBackground=lighten($MenuBar.background,10%)
|
||||
MenuBar.hoverBackground=@menuHoverBackground
|
||||
|
||||
|
||||
#---- MenuItemCheckBox ----
|
||||
@@ -187,6 +196,12 @@ MenuItemCheckBox.icon.disabledCheckmarkColor=#606060
|
||||
PasswordField.capsLockIconColor=#ffffff64
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
|
||||
Popup.dropShadowColor=#000
|
||||
Popup.dropShadowOpacity=0.25
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor=#5e5e5e
|
||||
@@ -218,7 +233,7 @@ Separator.foreground=#515151
|
||||
Slider.trackColor=#646464
|
||||
Slider.thumbColor=#A6A6A6
|
||||
Slider.tickColor=#888888
|
||||
Slider.hoverColor=darken(15%,autoInverse)
|
||||
Slider.hoverColor=darken($Slider.thumbColor,15%,derived autoInverse)
|
||||
Slider.disabledForeground=#4c5052
|
||||
|
||||
|
||||
@@ -253,11 +268,11 @@ TableHeader.bottomSeparatorColor=$TableHeader.separatorColor
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.selectedBackground=#64696C
|
||||
ToggleButton.selectedBackground=lighten($ToggleButton.background,10%,derived autoInverse)
|
||||
ToggleButton.selectedForeground=@foreground
|
||||
ToggleButton.disabledSelectedBackground=#525658
|
||||
ToggleButton.disabledSelectedBackground=lighten($ToggleButton.background,3%,derived autoInverse)
|
||||
|
||||
ToggleButton.toolbar.selectedBackground=#5c6164
|
||||
ToggleButton.toolbar.selectedBackground=lighten($ToggleButton.background,7%,derived autoInverse)
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
@@ -48,6 +48,7 @@ CheckBox.icon.selectedPressedBackground=#72A1D4
|
||||
|
||||
Component.focusWidth=2
|
||||
Component.innerFocusWidth=0
|
||||
Component.innerOutlineWidth=0
|
||||
Component.arrowType=triangle
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ ViewportUI=com.formdev.flatlaf.ui.FlatViewportUI
|
||||
#---- variables ----
|
||||
|
||||
@textComponentMargin=2,6,2,6
|
||||
@menuItemMargin=2,8,2,8
|
||||
@menuItemMargin=3,6,3,6
|
||||
|
||||
|
||||
#---- system colors ----
|
||||
@@ -185,6 +185,7 @@ ComboBox.padding=2,6,2,6
|
||||
|
||||
Component.focusWidth=0
|
||||
Component.innerFocusWidth={float}0.5
|
||||
Component.innerOutlineWidth={float}1
|
||||
Component.arc=5
|
||||
Component.minimumWidth=64
|
||||
Component.arrowType=chevron
|
||||
@@ -261,6 +262,13 @@ InternalFrame.maximizeIcon=com.formdev.flatlaf.icons.FlatInternalFrameMaximizeIc
|
||||
InternalFrame.minimizeIcon=com.formdev.flatlaf.icons.FlatInternalFrameMinimizeIcon
|
||||
InternalFrame.windowBindings=null
|
||||
|
||||
# drop shadow
|
||||
InternalFrame.dropShadowPainted=true
|
||||
InternalFrame.activeDropShadowColor=null
|
||||
InternalFrame.activeDropShadowInsets=5,5,6,6
|
||||
InternalFrame.inactiveDropShadowColor=null
|
||||
InternalFrame.inactiveDropShadowInsets=3,3,4,4
|
||||
|
||||
|
||||
#---- InternalFrameTitlePane ----
|
||||
|
||||
@@ -299,7 +307,7 @@ Menu.background=@menuBackground
|
||||
|
||||
MenuBar.border=com.formdev.flatlaf.ui.FlatMenuBarBorder
|
||||
MenuBar.background=@menuBackground
|
||||
MenuBar.itemMargins=3,3,3,3
|
||||
MenuBar.itemMargins=3,8,3,8
|
||||
|
||||
|
||||
#---- MenuItem ----
|
||||
@@ -311,9 +319,23 @@ MenuItem.margin=@menuItemMargin
|
||||
MenuItem.opaque=false
|
||||
MenuItem.borderPainted=true
|
||||
MenuItem.background=@menuBackground
|
||||
MenuItem.checkBackground=@menuCheckBackground
|
||||
MenuItem.checkMargins=2,2,2,2
|
||||
MenuItem.minimumWidth=72
|
||||
MenuItem.minimumIconSize=16,16
|
||||
MenuItem.iconTextGap=6
|
||||
MenuItem.textAcceleratorGap=24
|
||||
MenuItem.textNoAcceleratorGap=6
|
||||
MenuItem.acceleratorArrowGap=2
|
||||
MenuItem.acceleratorDelimiter=-
|
||||
[mac]MenuItem.acceleratorDelimiter=
|
||||
|
||||
# for MenuItem.selectionType=underline
|
||||
MenuItem.underlineSelectionBackground=@menuHoverBackground
|
||||
MenuItem.underlineSelectionCheckBackground=@menuCheckHoverBackground
|
||||
MenuItem.underlineSelectionColor=$TabbedPane.underlineColor
|
||||
MenuItem.underlineSelectionHeight=3
|
||||
|
||||
|
||||
#---- OptionPane ----
|
||||
|
||||
@@ -348,6 +370,12 @@ PasswordField.echoChar=\u2022
|
||||
PasswordField.capsLockIcon=com.formdev.flatlaf.icons.FlatCapsLockIcon
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
|
||||
Popup.dropShadowPainted=true
|
||||
Popup.dropShadowInsets=-4,-4,4,4
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.border=com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
||||
@@ -577,14 +605,6 @@ ToolBar.spacingBorder=$Button.toolbar.spacingInsets
|
||||
ToolTipManager.enableToolTipMode=activeApplication
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
ToolTip.border=4,6,4,6,$Component.borderColor
|
||||
ToolTip.borderInactive=null
|
||||
ToolTip.backgroundInactive=$ToolTip.background
|
||||
ToolTip.foregroundInactive=@disabledText
|
||||
|
||||
|
||||
#---- Tree ----
|
||||
|
||||
Tree.border=1,1,1,1
|
||||
|
||||
@@ -29,13 +29,12 @@
|
||||
@disabledText=#8C8C8C
|
||||
@textComponentBackground=#ffffff
|
||||
@menuBackground=#fff
|
||||
@menuHoverBackground=darken(@menuBackground,10%)
|
||||
@menuCheckBackground=darken(@menuBackground,10%)
|
||||
@menuCheckHoverBackground=darken(@menuBackground,20%)
|
||||
@cellFocusColor=#000000
|
||||
@icon=#afafaf
|
||||
|
||||
# Button
|
||||
@buttonHoverBackground=darken(3%,autoInverse)
|
||||
@buttonPressedBackground=darken(10%,autoInverse)
|
||||
|
||||
# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors)
|
||||
@dropCellBackground=lighten(List.selectionBackground,10%,lazy)
|
||||
@dropCellForeground=lazy(List.selectionForeground)
|
||||
@@ -57,7 +56,7 @@
|
||||
*.disabledBackground=@background
|
||||
*.disabledForeground=@disabledText
|
||||
*.disabledText=@disabledText
|
||||
*.acceleratorForeground=#505050
|
||||
*.acceleratorForeground=lighten(@foreground,30%)
|
||||
*.acceleratorSelectionForeground=@selectionForeground
|
||||
|
||||
|
||||
@@ -74,8 +73,8 @@ controlDkShadow=darken($controlShadow,15%)
|
||||
|
||||
Button.background=#ffffff
|
||||
Button.focusedBackground=#e3f1fa
|
||||
Button.hoverBackground=@buttonHoverBackground
|
||||
Button.pressedBackground=@buttonPressedBackground
|
||||
Button.hoverBackground=darken($Button.background,3%,derived autoInverse)
|
||||
Button.pressedBackground=darken($Button.background,10%,derived autoInverse)
|
||||
|
||||
Button.borderColor=$Component.borderColor
|
||||
Button.disabledBorderColor=$Component.disabledBorderColor
|
||||
@@ -85,16 +84,16 @@ Button.hoverBorderColor=$Button.focusedBorderColor
|
||||
Button.default.background=$Button.background
|
||||
Button.default.foreground=@foreground
|
||||
Button.default.focusedBackground=$Button.focusedBackground
|
||||
Button.default.hoverBackground=@buttonHoverBackground
|
||||
Button.default.pressedBackground=@buttonPressedBackground
|
||||
Button.default.hoverBackground=$Button.hoverBackground
|
||||
Button.default.pressedBackground=$Button.pressedBackground
|
||||
Button.default.borderColor=#4F9EE3
|
||||
Button.default.hoverBorderColor=$Button.hoverBorderColor
|
||||
Button.default.focusedBorderColor=$Button.focusedBorderColor
|
||||
Button.default.focusColor=$Component.focusColor
|
||||
Button.default.borderWidth=2
|
||||
|
||||
Button.toolbar.hoverBackground=#dfdfdf
|
||||
Button.toolbar.pressedBackground=#d8d8d8
|
||||
Button.toolbar.hoverBackground=darken($Button.background,12%,derived autoInverse)
|
||||
Button.toolbar.pressedBackground=darken($Button.background,15%,derived autoInverse)
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
@@ -107,8 +106,8 @@ CheckBox.icon.hoverBorderColor=$CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.background=#FFFFFF
|
||||
CheckBox.icon.disabledBackground=@background
|
||||
CheckBox.icon.focusedBackground=$Button.focusedBackground
|
||||
CheckBox.icon.hoverBackground=@buttonHoverBackground
|
||||
CheckBox.icon.pressedBackground=@buttonPressedBackground
|
||||
CheckBox.icon.hoverBackground=$Button.hoverBackground
|
||||
CheckBox.icon.pressedBackground=$Button.pressedBackground
|
||||
CheckBox.icon.selectedBackground=#FFFFFF
|
||||
CheckBox.icon.checkmarkColor=#4F9EE3
|
||||
CheckBox.icon.disabledCheckmarkColor=#ABABAB
|
||||
@@ -131,6 +130,13 @@ Component.disabledBorderColor=#cfcfcf
|
||||
Component.focusedBorderColor=#87afda
|
||||
Component.focusColor=#97c3f3
|
||||
Component.linkColor=#2470B3
|
||||
Component.grayFilter=25,-25,100
|
||||
|
||||
Component.error.borderColor=lighten(desaturate($Component.error.focusedBorderColor,20%),25%)
|
||||
Component.error.focusedBorderColor=#e53e4d
|
||||
Component.warning.borderColor=lighten(saturate($Component.warning.focusedBorderColor,25%),20%)
|
||||
Component.warning.focusedBorderColor=#e2a53a
|
||||
Component.custom.borderColor=lighten(desaturate(#f00,20%,derived),25%,derived)
|
||||
|
||||
|
||||
#---- Desktop ----
|
||||
@@ -158,13 +164,16 @@ InternalFrame.inactiveTitleForeground=@disabledText
|
||||
InternalFrame.activeBorderColor=darken($Component.borderColor,20%)
|
||||
InternalFrame.inactiveBorderColor=$Component.borderColor
|
||||
|
||||
InternalFrame.buttonHoverBackground=darken(10%,autoInverse)
|
||||
InternalFrame.buttonPressedBackground=darken(20%,autoInverse)
|
||||
InternalFrame.buttonHoverBackground=darken($InternalFrame.activeTitleBackground,10%,derived autoInverse)
|
||||
InternalFrame.buttonPressedBackground=darken($InternalFrame.activeTitleBackground,20%,derived autoInverse)
|
||||
InternalFrame.closeHoverBackground=lazy(Actions.Red)
|
||||
InternalFrame.closePressedBackground=darken(Actions.Red,10%,lazy)
|
||||
InternalFrame.closeHoverForeground=#fff
|
||||
InternalFrame.closePressedForeground=#fff
|
||||
|
||||
InternalFrame.activeDropShadowOpacity=0.25
|
||||
InternalFrame.inactiveDropShadowOpacity=0.5
|
||||
|
||||
|
||||
#---- List ----
|
||||
|
||||
@@ -180,7 +189,7 @@ Menu.icon.disabledArrowColor=#ABABAB
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.borderColor=#cdcdcd
|
||||
MenuBar.hoverBackground=darken($MenuBar.background,10%)
|
||||
MenuBar.hoverBackground=@menuHoverBackground
|
||||
|
||||
|
||||
#---- MenuItemCheckBox ----
|
||||
@@ -194,6 +203,12 @@ MenuItemCheckBox.icon.disabledCheckmarkColor=#ABABAB
|
||||
PasswordField.capsLockIconColor=#00000064
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
|
||||
Popup.dropShadowColor=#000
|
||||
Popup.dropShadowOpacity=0.15
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor=#adadad
|
||||
@@ -225,7 +240,7 @@ Separator.foreground=#d1d1d1
|
||||
Slider.trackColor=#c4c4c4
|
||||
Slider.thumbColor=#6e6e6e
|
||||
Slider.tickColor=#888888
|
||||
Slider.hoverColor=lighten(15%,autoInverse)
|
||||
Slider.hoverColor=lighten($Slider.thumbColor,15%,derived autoInverse)
|
||||
Slider.disabledForeground=#c0c0c0
|
||||
|
||||
|
||||
@@ -260,15 +275,16 @@ TableHeader.bottomSeparatorColor=$TableHeader.separatorColor
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.selectedBackground=#cfcfcf
|
||||
ToggleButton.selectedBackground=darken($ToggleButton.background,20%,derived autoInverse)
|
||||
ToggleButton.selectedForeground=@foreground
|
||||
ToggleButton.disabledSelectedBackground=#dfdfdf
|
||||
ToggleButton.disabledSelectedBackground=darken($ToggleButton.background,13%,derived autoInverse)
|
||||
|
||||
ToggleButton.toolbar.selectedBackground=#cfcfcf
|
||||
ToggleButton.toolbar.selectedBackground=$ToggleButton.selectedBackground
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
ToolTip.border=4,6,4,6,$InternalFrame.activeBorderColor
|
||||
ToolTip.background=#fafafa
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
#---- 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
|
||||
|
||||
@@ -23,3 +33,32 @@ Button.default.hoverBorderColor=null
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.hoverBorderColor=null
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.startBackground=$ToggleButton.background
|
||||
ToggleButton.endBackground=$ToggleButton.background
|
||||
[dark]ToggleButton.selectedBackground=lighten($ToggleButton.background,15%,derived autoInverse)
|
||||
[dark]ToggleButton.disabledSelectedBackground=lighten($ToggleButton.background,5%,derived autoInverse)
|
||||
|
||||
|
||||
#---- theme specific ----
|
||||
|
||||
[Gruvbox_Dark_Hard]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[High_contrast]ToggleButton.selectedBackground=#fff
|
||||
[High_contrast]ToggleButton.selectedForeground=#000
|
||||
[High_contrast]ToggleButton.disabledSelectedBackground=#444
|
||||
[High_contrast]ToggleButton.toolbar.selectedBackground=#fff
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#---- FileChooser ----
|
||||
|
||||
#fields
|
||||
FileChooser.lookInLabel.textAndMnemonic=Look &In:
|
||||
FileChooser.saveInLabelText=Save In:
|
||||
FileChooser.fileNameLabel.textAndMnemonic=File &Name:
|
||||
FileChooser.folderNameLabel.textAndMnemonic=Folder &name:
|
||||
FileChooser.filesOfTypeLabel.textAndMnemonic=Files of &Type:
|
||||
|
||||
# toolbar
|
||||
FileChooser.upFolderToolTipText=Up One Level
|
||||
FileChooser.upFolderAccessibleName=Up
|
||||
FileChooser.homeFolderToolTipText=Home
|
||||
FileChooser.homeFolderAccessibleName=Home
|
||||
FileChooser.newFolderToolTipText=Create New Folder
|
||||
FileChooser.newFolderAccessibleName=New Folder
|
||||
FileChooser.listViewButtonToolTipText=List
|
||||
FileChooser.listViewButtonAccessibleName=List
|
||||
FileChooser.detailsViewButtonToolTipText=Details
|
||||
FileChooser.detailsViewButtonAccessibleName=Details
|
||||
|
||||
# details table header
|
||||
FileChooser.fileNameHeaderText=Name
|
||||
FileChooser.fileSizeHeaderText=Size
|
||||
FileChooser.fileTypeHeaderText=Type
|
||||
FileChooser.fileDateHeaderText=Modified
|
||||
FileChooser.fileAttrHeaderText=Attributes
|
||||
|
||||
# popup menu
|
||||
FileChooser.viewMenuLabelText=View
|
||||
FileChooser.refreshActionLabelText=Refresh
|
||||
FileChooser.newFolderActionLabelText=New Folder
|
||||
FileChooser.listViewActionLabelText=List
|
||||
FileChooser.detailsViewActionLabelText=Details
|
||||
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#---- FileChooser ----
|
||||
|
||||
#fields
|
||||
FileChooser.lookInLabel.textAndMnemonic=Suchen &in:
|
||||
FileChooser.saveInLabelText=Speichern in:
|
||||
FileChooser.fileNameLabel.textAndMnemonic=&Dateiname:
|
||||
FileChooser.folderNameLabel.textAndMnemonic=Ordner&name:
|
||||
FileChooser.filesOfTypeLabel.textAndMnemonic=Datei&typ:
|
||||
|
||||
# toolbar
|
||||
FileChooser.upFolderToolTipText=Eine Ebene h\u00F6her
|
||||
FileChooser.upFolderAccessibleName=Nach oben
|
||||
FileChooser.homeFolderToolTipText=Home
|
||||
FileChooser.homeFolderAccessibleName=Home
|
||||
FileChooser.newFolderToolTipText=Neuen Ordner erstellen
|
||||
FileChooser.newFolderAccessibleName=Neuer Ordner
|
||||
FileChooser.listViewButtonToolTipText=Liste
|
||||
FileChooser.listViewButtonAccessibleName=Liste
|
||||
FileChooser.detailsViewButtonToolTipText=Details
|
||||
FileChooser.detailsViewButtonAccessibleName=Details
|
||||
|
||||
# details table header
|
||||
FileChooser.fileNameHeaderText=Name
|
||||
FileChooser.fileSizeHeaderText=Gr\u00F6\u00DFe
|
||||
FileChooser.fileTypeHeaderText=Typ
|
||||
FileChooser.fileDateHeaderText=\u00C4nderungsdatum
|
||||
FileChooser.fileAttrHeaderText=Attribute
|
||||
|
||||
# popup menu
|
||||
FileChooser.viewMenuLabelText=Ansicht
|
||||
FileChooser.refreshActionLabelText=Aktualisieren
|
||||
FileChooser.newFolderActionLabelText=Neuer Ordner
|
||||
FileChooser.listViewActionLabelText=Liste
|
||||
FileChooser.detailsViewActionLabelText=Details
|
||||
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#---- FileChooser ----
|
||||
|
||||
#fields
|
||||
FileChooser.lookInLabel.textAndMnemonic=Rechercher &dans:
|
||||
FileChooser.saveInLabelText=Enregistrer dans:
|
||||
FileChooser.fileNameLabel.textAndMnemonic=&Nom du fichier:
|
||||
FileChooser.folderNameLabel.textAndMnemonic=&Nom du dossier:
|
||||
FileChooser.filesOfTypeLabel.textAndMnemonic=&Type de fichier:
|
||||
|
||||
# toolbar
|
||||
FileChooser.upFolderToolTipText=Remonte d'un niveau
|
||||
FileChooser.upFolderAccessibleName=Monter
|
||||
FileChooser.homeFolderToolTipText=R\u00E9pertoire de base
|
||||
FileChooser.homeFolderAccessibleName=R\u00E9pertoire de base
|
||||
FileChooser.newFolderToolTipText=Cr\u00E9e un dossier
|
||||
FileChooser.newFolderAccessibleName=Nouveau dossier
|
||||
FileChooser.listViewButtonToolTipText=Liste
|
||||
FileChooser.listViewButtonAccessibleName=Liste
|
||||
FileChooser.detailsViewButtonToolTipText=D\u00E9tails
|
||||
FileChooser.detailsViewButtonAccessibleName=D\u00E9tails
|
||||
|
||||
# details table header
|
||||
FileChooser.fileNameHeaderText=Nom
|
||||
FileChooser.fileSizeHeaderText=Taille
|
||||
FileChooser.fileTypeHeaderText=Type
|
||||
FileChooser.fileDateHeaderText=Modifi\u00E9
|
||||
FileChooser.fileAttrHeaderText=Attributs
|
||||
|
||||
# popup menu
|
||||
FileChooser.viewMenuLabelText=Affichage
|
||||
FileChooser.refreshActionLabelText=Actualiser
|
||||
FileChooser.newFolderActionLabelText=Nouveau dossier
|
||||
FileChooser.listViewActionLabelText=Liste
|
||||
FileChooser.detailsViewActionLabelText=D\u00E9tails
|
||||
@@ -27,10 +27,18 @@ plugins {
|
||||
id( "com.jfrog.artifactory" )
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
// for using MigLayout snapshot
|
||||
url = uri( "https://oss.sonatype.org/content/repositories/snapshots/" )
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( project( ":flatlaf-extras" ) )
|
||||
implementation( "com.miglayout:miglayout-swing:5.2" )
|
||||
implementation( project( ":flatlaf-intellij-themes" ) )
|
||||
implementation( "com.miglayout:miglayout-swing:5.3-SNAPSHOT" )
|
||||
implementation( "com.jgoodies:jgoodies-forms:1.9.0" )
|
||||
}
|
||||
|
||||
@@ -38,12 +46,17 @@ tasks {
|
||||
jar {
|
||||
dependsOn( ":flatlaf-core:jar" )
|
||||
dependsOn( ":flatlaf-extras:jar" )
|
||||
dependsOn( ":flatlaf-intellij-themes:jar" )
|
||||
|
||||
manifest {
|
||||
attributes( "Main-Class" to "com.formdev.flatlaf.demo.FlatLafDemo" )
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 )
|
||||
attributes( "Multi-Release" to "true" )
|
||||
}
|
||||
|
||||
exclude( "META-INF/versions/**" )
|
||||
exclude( "module-info.class" )
|
||||
exclude( "META-INF/versions/*/module-info.class" )
|
||||
|
||||
// include all dependencies in jar
|
||||
from( {
|
||||
|
||||
@@ -114,6 +114,14 @@ class BasicComponentsPanel
|
||||
JScrollPane scrollPane12 = new JScrollPane();
|
||||
JTextPane textPane4 = new JTextPane();
|
||||
JTextPane textPane5 = new JTextPane();
|
||||
JLabel label3 = new JLabel();
|
||||
JTextField textField5 = new JTextField();
|
||||
JComboBox<String> comboBox7 = new JComboBox<>();
|
||||
JSpinner spinner3 = new JSpinner();
|
||||
JLabel label4 = new JLabel();
|
||||
JTextField textField7 = new JTextField();
|
||||
JComboBox<String> comboBox8 = new JComboBox<>();
|
||||
JSpinner spinner4 = new JSpinner();
|
||||
JPopupMenu popupMenu1 = new JPopupMenu();
|
||||
JMenuItem cutMenuItem = new JMenuItem();
|
||||
JMenuItem copyMenuItem = new JMenuItem();
|
||||
@@ -141,6 +149,8 @@ class BasicComponentsPanel
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//---- labelLabel ----
|
||||
@@ -179,9 +189,8 @@ class BasicComponentsPanel
|
||||
add(button5, "cell 3 1");
|
||||
|
||||
//---- button6 ----
|
||||
button6.setText("square");
|
||||
button6.setEnabled(false);
|
||||
button6.putClientProperty("JButton.buttonType", "square");
|
||||
button6.setText("round");
|
||||
button6.putClientProperty("JButton.buttonType", "roundRect");
|
||||
add(button6, "cell 4 1");
|
||||
|
||||
//---- button3 ----
|
||||
@@ -597,19 +606,61 @@ class BasicComponentsPanel
|
||||
textPane5.setText("no scroll pane");
|
||||
add(textPane5, "cell 5 11,growx");
|
||||
|
||||
//---- label3 ----
|
||||
label3.setText("Error hints:");
|
||||
add(label3, "cell 0 12");
|
||||
|
||||
//---- textField5 ----
|
||||
textField5.putClientProperty("JComponent.outline", "error");
|
||||
add(textField5, "cell 1 12,growx");
|
||||
|
||||
//---- comboBox7 ----
|
||||
comboBox7.putClientProperty("JComponent.outline", "error");
|
||||
comboBox7.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||
"editable"
|
||||
}));
|
||||
comboBox7.setEditable(true);
|
||||
add(comboBox7, "cell 2 12,growx");
|
||||
|
||||
//---- spinner3 ----
|
||||
spinner3.putClientProperty("JComponent.outline", "error");
|
||||
add(spinner3, "cell 3 12,growx");
|
||||
|
||||
//---- label4 ----
|
||||
label4.setText("Warning hints:");
|
||||
add(label4, "cell 0 13");
|
||||
|
||||
//---- textField7 ----
|
||||
textField7.putClientProperty("JComponent.outline", "warning");
|
||||
add(textField7, "cell 1 13,growx");
|
||||
|
||||
//---- comboBox8 ----
|
||||
comboBox8.putClientProperty("JComponent.outline", "warning");
|
||||
comboBox8.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||
"not editable"
|
||||
}));
|
||||
add(comboBox8, "cell 2 13,growx");
|
||||
|
||||
//---- spinner4 ----
|
||||
spinner4.putClientProperty("JComponent.outline", "warning");
|
||||
add(spinner4, "cell 3 13,growx");
|
||||
|
||||
//======== popupMenu1 ========
|
||||
{
|
||||
|
||||
//---- cutMenuItem ----
|
||||
cutMenuItem.setText("Cut");
|
||||
cutMenuItem.setMnemonic('C');
|
||||
popupMenu1.add(cutMenuItem);
|
||||
|
||||
//---- copyMenuItem ----
|
||||
copyMenuItem.setText("Copy");
|
||||
copyMenuItem.setMnemonic('O');
|
||||
popupMenu1.add(copyMenuItem);
|
||||
|
||||
//---- pasteMenuItem ----
|
||||
pasteMenuItem.setText("Paste");
|
||||
pasteMenuItem.setMnemonic('P');
|
||||
popupMenu1.add(pasteMenuItem);
|
||||
}
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "13.0.1" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -9,7 +9,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[][][][][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]para[][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
@@ -63,9 +63,8 @@ new FormModel {
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button6"
|
||||
"text": "square"
|
||||
"enabled": false
|
||||
"$client.JButton.buttonType": "square"
|
||||
"text": "round"
|
||||
"$client.JButton.buttonType": "roundRect"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 1"
|
||||
} )
|
||||
@@ -592,23 +591,83 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 11,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"text": "Error hints:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 12"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "textField5"
|
||||
"$client.JComponent.outline": "error"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 12,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||
name: "comboBox7"
|
||||
"$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: "spinner3"
|
||||
"$client.JComponent.outline": "error"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 12,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label4"
|
||||
"text": "Warning hints:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 13"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "textField7"
|
||||
"$client.JComponent.outline": "warning"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 13,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||
name: "comboBox8"
|
||||
"$client.JComponent.outline": "warning"
|
||||
"model": new javax.swing.DefaultComboBoxModel {
|
||||
selectedItem: "not editable"
|
||||
addElement( "not editable" )
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 13,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JSpinner" ) {
|
||||
name: "spinner4"
|
||||
"$client.JComponent.outline": "warning"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 13,growx"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 440 )
|
||||
"size": new java.awt.Dimension( 920, 440 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
|
||||
name: "popupMenu1"
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "cutMenuItem"
|
||||
"text": "Cut"
|
||||
"mnemonic": 67
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "copyMenuItem"
|
||||
"text": "Copy"
|
||||
"mnemonic": 79
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "pasteMenuItem"
|
||||
"text": "Paste"
|
||||
"mnemonic": 80
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 500 )
|
||||
|
||||
@@ -63,7 +63,7 @@ class ControlBar
|
||||
(SystemInfo.IS_LINUX && className.equals( "com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ) )
|
||||
name += " (F9)";
|
||||
else if( className.equals( MetalLookAndFeel.class.getName() ) )
|
||||
name += " (F10)";
|
||||
name += " (F12)";
|
||||
else if( className.equals( NimbusLookAndFeel.class.getName() ) )
|
||||
name += " (F11)";
|
||||
|
||||
@@ -106,7 +106,7 @@ class ControlBar
|
||||
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.apple.laf.AquaLookAndFeel" );
|
||||
else if( SystemInfo.IS_LINUX )
|
||||
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.gtk.GTKLookAndFeel" );
|
||||
registerSwitchToLookAndFeel( KeyEvent.VK_F10, MetalLookAndFeel.class.getName() );
|
||||
registerSwitchToLookAndFeel( KeyEvent.VK_F12, MetalLookAndFeel.class.getName() );
|
||||
registerSwitchToLookAndFeel( KeyEvent.VK_F11, NimbusLookAndFeel.class.getName() );
|
||||
|
||||
// register ESC key to close frame
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.demo.extras.*;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.*;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -59,6 +60,15 @@ class DemoFrame
|
||||
} );
|
||||
}
|
||||
|
||||
private void underlineMenuSelection() {
|
||||
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
|
||||
}
|
||||
|
||||
private void alwaysShowMnemonics() {
|
||||
UIManager.put( "Component.hideMnemonics", !alwaysShowMnemonicsMenuItem.isSelected() );
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void fontFamilyChanged( ActionEvent e ) {
|
||||
String fontFamily = e.getActionCommand();
|
||||
|
||||
@@ -125,6 +135,7 @@ class DemoFrame
|
||||
JMenuItem projectViewMenuItem = new JMenuItem();
|
||||
JMenuItem structureViewMenuItem = new JMenuItem();
|
||||
JMenuItem propertiesViewMenuItem = new JMenuItem();
|
||||
JMenuItem menuItem1 = new JMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem2 = new JRadioButtonMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem3 = new JRadioButtonMenuItem();
|
||||
@@ -132,6 +143,9 @@ class DemoFrame
|
||||
JMenuItem restoreFontMenuItem = new JMenuItem();
|
||||
JMenuItem incrFontMenuItem = new JMenuItem();
|
||||
JMenuItem decrFontMenuItem = new JMenuItem();
|
||||
JMenu optionsMenu = new JMenu();
|
||||
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
|
||||
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
|
||||
JMenu helpMenu = new JMenu();
|
||||
JMenuItem aboutMenuItem = new JMenuItem();
|
||||
JToolBar toolBar1 = new JToolBar();
|
||||
@@ -149,6 +163,7 @@ class DemoFrame
|
||||
DataComponentsPanel dataComponentsPanel = new DataComponentsPanel();
|
||||
TabsPanel tabsPanel = new TabsPanel();
|
||||
OptionPanePanel optionPanePanel = new OptionPanePanel();
|
||||
ExtrasPanel extrasPanel1 = new ExtrasPanel();
|
||||
controlBar = new ControlBar();
|
||||
IJThemesPanel themesPanel = new IJThemesPanel();
|
||||
|
||||
@@ -308,6 +323,10 @@ class DemoFrame
|
||||
menu1.add(propertiesViewMenuItem);
|
||||
}
|
||||
viewMenu.add(menu1);
|
||||
|
||||
//---- menuItem1 ----
|
||||
menuItem1.setText("<html>some <b color=\"red\">HTML</b> <i color=\"blue\">text</i></html>");
|
||||
viewMenu.add(menuItem1);
|
||||
viewMenu.addSeparator();
|
||||
|
||||
//---- radioButtonMenuItem1 ----
|
||||
@@ -355,6 +374,22 @@ class DemoFrame
|
||||
}
|
||||
menuBar1.add(fontMenu);
|
||||
|
||||
//======== optionsMenu ========
|
||||
{
|
||||
optionsMenu.setText("Options");
|
||||
|
||||
//---- underlineMenuSelectionMenuItem ----
|
||||
underlineMenuSelectionMenuItem.setText("Use underline menu selection");
|
||||
underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection());
|
||||
optionsMenu.add(underlineMenuSelectionMenuItem);
|
||||
|
||||
//---- alwaysShowMnemonicsMenuItem ----
|
||||
alwaysShowMnemonicsMenuItem.setText("Always show mnemonics");
|
||||
alwaysShowMnemonicsMenuItem.addActionListener(e -> alwaysShowMnemonics());
|
||||
optionsMenu.add(alwaysShowMnemonicsMenuItem);
|
||||
}
|
||||
menuBar1.add(optionsMenu);
|
||||
|
||||
//======== helpMenu ========
|
||||
{
|
||||
helpMenu.setText("Help");
|
||||
@@ -425,6 +460,7 @@ class DemoFrame
|
||||
tabbedPane.addTab("Data Components", dataComponentsPanel);
|
||||
tabbedPane.addTab("SplitPane & Tabs", tabsPanel);
|
||||
tabbedPane.addTab("Option Pane", optionPanePanel);
|
||||
tabbedPane.addTab("Extras", extrasPanel1);
|
||||
}
|
||||
contentPanel.add(tabbedPane, "cell 0 0");
|
||||
}
|
||||
@@ -481,6 +517,8 @@ class DemoFrame
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JMenu fontMenu;
|
||||
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
|
||||
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
|
||||
private JTabbedPane tabbedPane;
|
||||
private ControlBar controlBar;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
@@ -93,6 +93,11 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"title": "Option Pane"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.extras.ExtrasPanel" ) {
|
||||
name: "extrasPanel1"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"title": "Extras"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
@@ -259,6 +264,10 @@ new FormModel {
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem1"
|
||||
"text": "<html>some <b color=\"red\">HTML</b> <i color=\"blue\">text</i></html>"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator8"
|
||||
} )
|
||||
@@ -310,6 +319,26 @@ new FormModel {
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decrFont", false ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "optionsMenu"
|
||||
"text": "Options"
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "underlineMenuSelectionMenuItem"
|
||||
"text": "Use underline menu selection"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "underlineMenuSelection", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "alwaysShowMnemonicsMenuItem"
|
||||
"text": "Always show mnemonics"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "alwaysShowMnemonics", false ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "helpMenu"
|
||||
"text": "Help"
|
||||
|
||||
@@ -22,9 +22,9 @@ import java.util.prefs.Preferences;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import com.formdev.flatlaf.FlatPropertiesLaf;
|
||||
import com.formdev.flatlaf.IntelliJTheme;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel.PropertiesLaf;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ public class DemoPrefs
|
||||
if( IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) {
|
||||
String theme = state.get( KEY_LAF_THEME, "" );
|
||||
if( theme.startsWith( RESOURCE_PREFIX ) )
|
||||
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( theme.substring( RESOURCE_PREFIX.length() ) ) );
|
||||
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( IJThemesPanel.THEMES_PACKAGE + theme.substring( RESOURCE_PREFIX.length() ) ) );
|
||||
else if( theme.startsWith( FILE_PREFIX ) )
|
||||
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( theme.substring( FILE_PREFIX.length() ) ) ) );
|
||||
else
|
||||
@@ -68,12 +68,12 @@ public class DemoPrefs
|
||||
|
||||
if( !theme.isEmpty() )
|
||||
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
|
||||
} else if( IJThemesPanel.PropertiesLaf.class.getName().equals( lafClassName ) ) {
|
||||
} 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.install( new PropertiesLaf( themeName, themeFile ) );
|
||||
FlatLaf.install( new FlatPropertiesLaf( themeName, themeFile ) );
|
||||
} else
|
||||
FlatLightLaf.install();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.demo;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -27,6 +28,9 @@ public class FlatLafDemo
|
||||
static final String KEY_TAB = "tab";
|
||||
|
||||
public static void main( String[] args ) {
|
||||
if( SystemInfo.IS_MAC )
|
||||
System.setProperty( "apple.laf.useScreenMenuBar", "true" );
|
||||
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
DemoPrefs.init( PREFS_ROOT_PATH );
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ class MoreComponentsPanel
|
||||
JButton button7 = new JButton();
|
||||
JButton button8 = new JButton();
|
||||
JToggleButton toggleButton6 = new JToggleButton();
|
||||
JButton button1 = new JButton();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
@@ -380,6 +381,11 @@ class MoreComponentsPanel
|
||||
toggleButton6.setIcon(UIManager.getIcon("Tree.leafIcon"));
|
||||
toggleButton6.setSelected(true);
|
||||
toolBar1.add(toggleButton6);
|
||||
|
||||
//---- button1 ----
|
||||
button1.setIcon(new ImageIcon(getClass().getResource("/com/formdev/flatlaf/demo/icons/intellij-showWriteAccess.png")));
|
||||
button1.setEnabled(false);
|
||||
toolBar1.add(button1);
|
||||
}
|
||||
add(toolBar1, "cell 1 10 3 1,growx");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -355,6 +355,11 @@ new FormModel {
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.leafIcon" )
|
||||
"selected": true
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button1"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/demo/icons/intellij-showWriteAccess.png" )
|
||||
"enabled": false
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 10 3 1,growx"
|
||||
} )
|
||||
|
||||
@@ -27,7 +27,7 @@ import net.miginfocom.swing.*;
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class OptionPanePanel
|
||||
extends JScrollPane
|
||||
extends JPanel
|
||||
{
|
||||
OptionPanePanel() {
|
||||
initComponents();
|
||||
@@ -48,6 +48,7 @@ class OptionPanePanel
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JScrollPane scrollPane1 = new JScrollPane();
|
||||
ScrollablePanel panel9 = new ScrollablePanel();
|
||||
JLabel plainLabel = new JLabel();
|
||||
JPanel panel1 = new JPanel();
|
||||
@@ -83,200 +84,206 @@ class OptionPanePanel
|
||||
OptionPanePanel.ShowDialogLinkLabel customShowDialogLabel = new OptionPanePanel.ShowDialogLinkLabel();
|
||||
|
||||
//======== this ========
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
//======== panel9 ========
|
||||
//======== scrollPane1 ========
|
||||
{
|
||||
panel9.setLayout(new MigLayout(
|
||||
"flowy,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]"));
|
||||
scrollPane1.setBorder(BorderFactory.createEmptyBorder());
|
||||
|
||||
//---- plainLabel ----
|
||||
plainLabel.setText("Plain");
|
||||
panel9.add(plainLabel, "cell 0 0");
|
||||
|
||||
//======== panel1 ========
|
||||
//======== panel9 ========
|
||||
{
|
||||
panel1.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel1.setLayout(new BorderLayout());
|
||||
panel9.setLayout(new MigLayout(
|
||||
"flowy,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]" +
|
||||
"[top]"));
|
||||
|
||||
//---- plainOptionPane ----
|
||||
plainOptionPane.setMessage("Hello world.");
|
||||
panel1.add(plainOptionPane, BorderLayout.CENTER);
|
||||
//---- plainLabel ----
|
||||
plainLabel.setText("Plain");
|
||||
panel9.add(plainLabel, "cell 0 0");
|
||||
|
||||
//======== panel1 ========
|
||||
{
|
||||
panel1.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel1.setLayout(new BorderLayout());
|
||||
|
||||
//---- plainOptionPane ----
|
||||
plainOptionPane.setMessage("Hello world.");
|
||||
panel1.add(plainOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel1, "cell 1 0");
|
||||
|
||||
//---- plainShowDialogLabel ----
|
||||
plainShowDialogLabel.setOptionPane(plainOptionPane);
|
||||
plainShowDialogLabel.setTitleLabel(plainLabel);
|
||||
panel9.add(plainShowDialogLabel, "cell 2 0");
|
||||
|
||||
//---- errorLabel ----
|
||||
errorLabel.setText("Error");
|
||||
panel9.add(errorLabel, "cell 0 1");
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel2.setLayout(new BorderLayout());
|
||||
|
||||
//---- errorOptionPane ----
|
||||
errorOptionPane.setMessageType(JOptionPane.ERROR_MESSAGE);
|
||||
errorOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
errorOptionPane.setMessage("Your PC ran into a problem. Buy a new one.");
|
||||
panel2.add(errorOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel2, "cell 1 1");
|
||||
|
||||
//---- errorShowDialogLabel ----
|
||||
errorShowDialogLabel.setTitleLabel(errorLabel);
|
||||
errorShowDialogLabel.setOptionPane(errorOptionPane);
|
||||
panel9.add(errorShowDialogLabel, "cell 2 1");
|
||||
|
||||
//---- informationLabel ----
|
||||
informationLabel.setText("Information");
|
||||
panel9.add(informationLabel, "cell 0 2");
|
||||
|
||||
//======== panel3 ========
|
||||
{
|
||||
panel3.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel3.setLayout(new BorderLayout());
|
||||
|
||||
//---- informationOptionPane ----
|
||||
informationOptionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
|
||||
informationOptionPane.setOptionType(JOptionPane.YES_NO_OPTION);
|
||||
informationOptionPane.setMessage("Text with\nmultiple lines\n(use \\n to separate lines)");
|
||||
panel3.add(informationOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel3, "cell 1 2");
|
||||
|
||||
//---- informationShowDialogLabel ----
|
||||
informationShowDialogLabel.setOptionPane(informationOptionPane);
|
||||
informationShowDialogLabel.setTitleLabel(informationLabel);
|
||||
panel9.add(informationShowDialogLabel, "cell 2 2");
|
||||
|
||||
//---- questionLabel ----
|
||||
questionLabel.setText("Question");
|
||||
panel9.add(questionLabel, "cell 0 3");
|
||||
|
||||
//======== panel4 ========
|
||||
{
|
||||
panel4.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel4.setLayout(new BorderLayout());
|
||||
|
||||
//---- questionOptionPane ----
|
||||
questionOptionPane.setMessageType(JOptionPane.QUESTION_MESSAGE);
|
||||
questionOptionPane.setOptionType(JOptionPane.YES_NO_CANCEL_OPTION);
|
||||
questionOptionPane.setMessage("Answer the question. What question? Don't know. Just writing useless text to make this longer than 80 characters.");
|
||||
panel4.add(questionOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel4, "cell 1 3");
|
||||
|
||||
//---- questionShowDialogLabel ----
|
||||
questionShowDialogLabel.setOptionPane(questionOptionPane);
|
||||
questionShowDialogLabel.setTitleLabel(questionLabel);
|
||||
panel9.add(questionShowDialogLabel, "cell 2 3");
|
||||
|
||||
//---- warningLabel ----
|
||||
warningLabel.setText("Warning");
|
||||
panel9.add(warningLabel, "cell 0 4");
|
||||
|
||||
//======== panel5 ========
|
||||
{
|
||||
panel5.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel5.setLayout(new BorderLayout());
|
||||
|
||||
//---- warningOptionPane ----
|
||||
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
|
||||
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
warningOptionPane.setMessage("<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines.");
|
||||
panel5.add(warningOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel5, "cell 1 4");
|
||||
|
||||
//---- warningShowDialogLabel ----
|
||||
warningShowDialogLabel.setOptionPane(warningOptionPane);
|
||||
warningShowDialogLabel.setTitleLabel(warningLabel);
|
||||
panel9.add(warningShowDialogLabel, "cell 2 4");
|
||||
|
||||
//---- inputLabel ----
|
||||
inputLabel.setText("Input");
|
||||
panel9.add(inputLabel, "cell 0 5");
|
||||
|
||||
//======== panel7 ========
|
||||
{
|
||||
panel7.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel7.setLayout(new BorderLayout());
|
||||
|
||||
//---- inputOptionPane ----
|
||||
inputOptionPane.setWantsInput(true);
|
||||
inputOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
inputOptionPane.setMessage("Enter whatever you want:");
|
||||
panel7.add(inputOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel7, "cell 1 5");
|
||||
|
||||
//---- inputShowDialogLabel ----
|
||||
inputShowDialogLabel.setOptionPane(inputOptionPane);
|
||||
inputShowDialogLabel.setTitleLabel(inputLabel);
|
||||
panel9.add(inputShowDialogLabel, "cell 2 5");
|
||||
|
||||
//---- inputIconLabel ----
|
||||
inputIconLabel.setText("Input + icon");
|
||||
panel9.add(inputIconLabel, "cell 0 6");
|
||||
|
||||
//======== panel8 ========
|
||||
{
|
||||
panel8.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel8.setLayout(new BorderLayout());
|
||||
|
||||
//---- inputIconOptionPane ----
|
||||
inputIconOptionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
|
||||
inputIconOptionPane.setWantsInput(true);
|
||||
inputIconOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
inputIconOptionPane.setMessage("Enter something:");
|
||||
panel8.add(inputIconOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel8, "cell 1 6");
|
||||
|
||||
//---- inputIconShowDialogLabel ----
|
||||
inputIconShowDialogLabel.setTitleLabel(inputIconLabel);
|
||||
inputIconShowDialogLabel.setOptionPane(inputIconOptionPane);
|
||||
panel9.add(inputIconShowDialogLabel, "cell 2 6");
|
||||
|
||||
//---- customLabel ----
|
||||
customLabel.setText("Custom");
|
||||
panel9.add(customLabel, "cell 0 7");
|
||||
|
||||
//======== panel6 ========
|
||||
{
|
||||
panel6.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel6.setLayout(new BorderLayout());
|
||||
|
||||
//---- customOptionPane ----
|
||||
customOptionPane.setIcon(UIManager.getIcon("Tree.leafIcon"));
|
||||
panel6.add(customOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel6, "cell 1 7");
|
||||
|
||||
//---- customShowDialogLabel ----
|
||||
customShowDialogLabel.setOptionPane(customOptionPane);
|
||||
customShowDialogLabel.setTitleLabel(customLabel);
|
||||
panel9.add(customShowDialogLabel, "cell 2 7");
|
||||
}
|
||||
panel9.add(panel1, "cell 1 0");
|
||||
|
||||
//---- plainShowDialogLabel ----
|
||||
plainShowDialogLabel.setOptionPane(plainOptionPane);
|
||||
plainShowDialogLabel.setTitleLabel(plainLabel);
|
||||
panel9.add(plainShowDialogLabel, "cell 2 0");
|
||||
|
||||
//---- errorLabel ----
|
||||
errorLabel.setText("Error");
|
||||
panel9.add(errorLabel, "cell 0 1");
|
||||
|
||||
//======== panel2 ========
|
||||
{
|
||||
panel2.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel2.setLayout(new BorderLayout());
|
||||
|
||||
//---- errorOptionPane ----
|
||||
errorOptionPane.setMessageType(JOptionPane.ERROR_MESSAGE);
|
||||
errorOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
errorOptionPane.setMessage("Your PC ran into a problem. Buy a new one.");
|
||||
panel2.add(errorOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel2, "cell 1 1");
|
||||
|
||||
//---- errorShowDialogLabel ----
|
||||
errorShowDialogLabel.setTitleLabel(errorLabel);
|
||||
errorShowDialogLabel.setOptionPane(errorOptionPane);
|
||||
panel9.add(errorShowDialogLabel, "cell 2 1");
|
||||
|
||||
//---- informationLabel ----
|
||||
informationLabel.setText("Information");
|
||||
panel9.add(informationLabel, "cell 0 2");
|
||||
|
||||
//======== panel3 ========
|
||||
{
|
||||
panel3.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel3.setLayout(new BorderLayout());
|
||||
|
||||
//---- informationOptionPane ----
|
||||
informationOptionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
|
||||
informationOptionPane.setOptionType(JOptionPane.YES_NO_OPTION);
|
||||
informationOptionPane.setMessage("Text with\nmultiple lines\n(use \\n to separate lines)");
|
||||
panel3.add(informationOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel3, "cell 1 2");
|
||||
|
||||
//---- informationShowDialogLabel ----
|
||||
informationShowDialogLabel.setOptionPane(informationOptionPane);
|
||||
informationShowDialogLabel.setTitleLabel(informationLabel);
|
||||
panel9.add(informationShowDialogLabel, "cell 2 2");
|
||||
|
||||
//---- questionLabel ----
|
||||
questionLabel.setText("Question");
|
||||
panel9.add(questionLabel, "cell 0 3");
|
||||
|
||||
//======== panel4 ========
|
||||
{
|
||||
panel4.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel4.setLayout(new BorderLayout());
|
||||
|
||||
//---- questionOptionPane ----
|
||||
questionOptionPane.setMessageType(JOptionPane.QUESTION_MESSAGE);
|
||||
questionOptionPane.setOptionType(JOptionPane.YES_NO_CANCEL_OPTION);
|
||||
questionOptionPane.setMessage("Answer the question. What question? Don't know. Just writing useless text to make this longer than 80 characters.");
|
||||
panel4.add(questionOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel4, "cell 1 3");
|
||||
|
||||
//---- questionShowDialogLabel ----
|
||||
questionShowDialogLabel.setOptionPane(questionOptionPane);
|
||||
questionShowDialogLabel.setTitleLabel(questionLabel);
|
||||
panel9.add(questionShowDialogLabel, "cell 2 3");
|
||||
|
||||
//---- warningLabel ----
|
||||
warningLabel.setText("Warning");
|
||||
panel9.add(warningLabel, "cell 0 4");
|
||||
|
||||
//======== panel5 ========
|
||||
{
|
||||
panel5.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel5.setLayout(new BorderLayout());
|
||||
|
||||
//---- warningOptionPane ----
|
||||
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
|
||||
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
warningOptionPane.setMessage("<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines.");
|
||||
panel5.add(warningOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel5, "cell 1 4");
|
||||
|
||||
//---- warningShowDialogLabel ----
|
||||
warningShowDialogLabel.setOptionPane(warningOptionPane);
|
||||
warningShowDialogLabel.setTitleLabel(warningLabel);
|
||||
panel9.add(warningShowDialogLabel, "cell 2 4");
|
||||
|
||||
//---- inputLabel ----
|
||||
inputLabel.setText("Input");
|
||||
panel9.add(inputLabel, "cell 0 5");
|
||||
|
||||
//======== panel7 ========
|
||||
{
|
||||
panel7.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel7.setLayout(new BorderLayout());
|
||||
|
||||
//---- inputOptionPane ----
|
||||
inputOptionPane.setWantsInput(true);
|
||||
inputOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
inputOptionPane.setMessage("Enter whatever you want:");
|
||||
panel7.add(inputOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel7, "cell 1 5");
|
||||
|
||||
//---- inputShowDialogLabel ----
|
||||
inputShowDialogLabel.setOptionPane(inputOptionPane);
|
||||
inputShowDialogLabel.setTitleLabel(inputLabel);
|
||||
panel9.add(inputShowDialogLabel, "cell 2 5");
|
||||
|
||||
//---- inputIconLabel ----
|
||||
inputIconLabel.setText("Input + icon");
|
||||
panel9.add(inputIconLabel, "cell 0 6");
|
||||
|
||||
//======== panel8 ========
|
||||
{
|
||||
panel8.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel8.setLayout(new BorderLayout());
|
||||
|
||||
//---- inputIconOptionPane ----
|
||||
inputIconOptionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
|
||||
inputIconOptionPane.setWantsInput(true);
|
||||
inputIconOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
|
||||
inputIconOptionPane.setMessage("Enter something:");
|
||||
panel8.add(inputIconOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel8, "cell 1 6");
|
||||
|
||||
//---- inputIconShowDialogLabel ----
|
||||
inputIconShowDialogLabel.setTitleLabel(inputIconLabel);
|
||||
inputIconShowDialogLabel.setOptionPane(inputIconOptionPane);
|
||||
panel9.add(inputIconShowDialogLabel, "cell 2 6");
|
||||
|
||||
//---- customLabel ----
|
||||
customLabel.setText("Custom");
|
||||
panel9.add(customLabel, "cell 0 7");
|
||||
|
||||
//======== panel6 ========
|
||||
{
|
||||
panel6.setBorder(LineBorder.createGrayLineBorder());
|
||||
panel6.setLayout(new BorderLayout());
|
||||
|
||||
//---- customOptionPane ----
|
||||
customOptionPane.setIcon(UIManager.getIcon("Tree.leafIcon"));
|
||||
panel6.add(customOptionPane, BorderLayout.CENTER);
|
||||
}
|
||||
panel9.add(panel6, "cell 1 7");
|
||||
|
||||
//---- customShowDialogLabel ----
|
||||
customShowDialogLabel.setOptionPane(customOptionPane);
|
||||
customShowDialogLabel.setTitleLabel(customLabel);
|
||||
panel9.add(customShowDialogLabel, "cell 2 7");
|
||||
scrollPane1.setViewportView(panel9);
|
||||
}
|
||||
setViewportView(panel9);
|
||||
add(scrollPane1, BorderLayout.CENTER);
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
|
||||
@@ -6,240 +6,245 @@ new FormModel {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.defaultVariableLocal": true
|
||||
}
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "this"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "flowy,hidemode 3"
|
||||
"$columnConstraints": "[][][fill]"
|
||||
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
|
||||
} ) {
|
||||
name: "panel9"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "plainLabel"
|
||||
"text": "Plain"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel1"
|
||||
"border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color gray, 1, false )
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "plainOptionPane"
|
||||
"message": "Hello world."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane1"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "flowy,hidemode 3"
|
||||
"$columnConstraints": "[][][fill]"
|
||||
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
|
||||
} ) {
|
||||
name: "panel9"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "plainLabel"
|
||||
"text": "Plain"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "plainShowDialogLabel"
|
||||
"optionPane": new FormReference( "plainOptionPane" )
|
||||
"titleLabel": new FormReference( "plainLabel" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "errorLabel"
|
||||
"text": "Error"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel2"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "errorOptionPane"
|
||||
"messageType": 0
|
||||
"optionType": 2
|
||||
"message": "Your PC ran into a problem. Buy a new one."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel1"
|
||||
"border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color gray, 1, false )
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "plainOptionPane"
|
||||
"message": "Hello world."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "errorShowDialogLabel"
|
||||
"titleLabel": new FormReference( "errorLabel" )
|
||||
"optionPane": new FormReference( "errorOptionPane" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "informationLabel"
|
||||
"text": "Information"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel3"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "informationOptionPane"
|
||||
"messageType": 1
|
||||
"optionType": 0
|
||||
"message": "Text with\nmultiple lines\n(use \\n to separate lines)"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "informationShowDialogLabel"
|
||||
"optionPane": new FormReference( "informationOptionPane" )
|
||||
"titleLabel": new FormReference( "informationLabel" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "questionLabel"
|
||||
"text": "Question"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel4"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "questionOptionPane"
|
||||
"messageType": 3
|
||||
"optionType": 1
|
||||
"message": "Answer the question. What question? Don't know. Just writing useless text to make this longer than 80 characters."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "questionShowDialogLabel"
|
||||
"optionPane": new FormReference( "questionOptionPane" )
|
||||
"titleLabel": new FormReference( "questionLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "warningLabel"
|
||||
"text": "Warning"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel5"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "warningOptionPane"
|
||||
"messageType": 2
|
||||
"optionType": 2
|
||||
"message": "<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "warningShowDialogLabel"
|
||||
"optionPane": new FormReference( "warningOptionPane" )
|
||||
"titleLabel": new FormReference( "warningLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputLabel"
|
||||
"text": "Input"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel7"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "inputOptionPane"
|
||||
"wantsInput": true
|
||||
"optionType": 2
|
||||
"message": "Enter whatever you want:"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "inputShowDialogLabel"
|
||||
"optionPane": new FormReference( "inputOptionPane" )
|
||||
"titleLabel": new FormReference( "inputLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputIconLabel"
|
||||
"text": "Input + icon"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel8"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "inputIconOptionPane"
|
||||
"messageType": 1
|
||||
"wantsInput": true
|
||||
"optionType": 2
|
||||
"message": "Enter something:"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "inputIconShowDialogLabel"
|
||||
"titleLabel": new FormReference( "inputIconLabel" )
|
||||
"optionPane": new FormReference( "inputIconOptionPane" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "customLabel"
|
||||
"text": "Custom"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel6"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "customOptionPane"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.leafIcon" )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "plainShowDialogLabel"
|
||||
"optionPane": new FormReference( "plainOptionPane" )
|
||||
"titleLabel": new FormReference( "plainLabel" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "errorLabel"
|
||||
"text": "Error"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel2"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "errorOptionPane"
|
||||
"messageType": 0
|
||||
"optionType": 2
|
||||
"message": "Your PC ran into a problem. Buy a new one."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "errorShowDialogLabel"
|
||||
"titleLabel": new FormReference( "errorLabel" )
|
||||
"optionPane": new FormReference( "errorOptionPane" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "informationLabel"
|
||||
"text": "Information"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel3"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "informationOptionPane"
|
||||
"messageType": 1
|
||||
"optionType": 0
|
||||
"message": "Text with\nmultiple lines\n(use \\n to separate lines)"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "informationShowDialogLabel"
|
||||
"optionPane": new FormReference( "informationOptionPane" )
|
||||
"titleLabel": new FormReference( "informationLabel" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "questionLabel"
|
||||
"text": "Question"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel4"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "questionOptionPane"
|
||||
"messageType": 3
|
||||
"optionType": 1
|
||||
"message": "Answer the question. What question? Don't know. Just writing useless text to make this longer than 80 characters."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "questionShowDialogLabel"
|
||||
"optionPane": new FormReference( "questionOptionPane" )
|
||||
"titleLabel": new FormReference( "questionLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 3"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "warningLabel"
|
||||
"text": "Warning"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel5"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "warningOptionPane"
|
||||
"messageType": 2
|
||||
"optionType": 2
|
||||
"message": "<html>I like <b>bold</b>,<br> and I like <i>italic</i>,<br> and I like to have<br> many lines.<br> Lots of lines."
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "warningShowDialogLabel"
|
||||
"optionPane": new FormReference( "warningOptionPane" )
|
||||
"titleLabel": new FormReference( "warningLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputLabel"
|
||||
"text": "Input"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel7"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "inputOptionPane"
|
||||
"wantsInput": true
|
||||
"optionType": 2
|
||||
"message": "Enter whatever you want:"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "inputShowDialogLabel"
|
||||
"optionPane": new FormReference( "inputOptionPane" )
|
||||
"titleLabel": new FormReference( "inputLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputIconLabel"
|
||||
"text": "Input + icon"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel8"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "inputIconOptionPane"
|
||||
"messageType": 1
|
||||
"wantsInput": true
|
||||
"optionType": 2
|
||||
"message": "Enter something:"
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "inputIconShowDialogLabel"
|
||||
"titleLabel": new FormReference( "inputIconLabel" )
|
||||
"optionPane": new FormReference( "inputIconOptionPane" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "customLabel"
|
||||
"text": "Custom"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
|
||||
name: "panel6"
|
||||
"border": #LineBorder0
|
||||
add( new FormComponent( "javax.swing.JOptionPane" ) {
|
||||
name: "customOptionPane"
|
||||
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.leafIcon" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "customShowDialogLabel"
|
||||
"optionPane": new FormReference( "customOptionPane" )
|
||||
"titleLabel": new FormReference( "customLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.demo.OptionPanePanel$ShowDialogLinkLabel" ) {
|
||||
name: "customShowDialogLabel"
|
||||
"optionPane": new FormReference( "customOptionPane" )
|
||||
"titleLabel": new FormReference( "customLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
"value": "Center"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.demo.extras;
|
||||
|
||||
import javax.swing.*;
|
||||
import com.formdev.flatlaf.extras.*;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class ExtrasPanel
|
||||
extends JPanel
|
||||
{
|
||||
public ExtrasPanel() {
|
||||
initComponents();
|
||||
|
||||
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
|
||||
|
||||
addSVGIcon( "actions/copy.svg" );
|
||||
addSVGIcon( "actions/colors.svg" );
|
||||
addSVGIcon( "actions/execute.svg" );
|
||||
addSVGIcon( "actions/suspend.svg" );
|
||||
addSVGIcon( "actions/intentionBulb.svg" );
|
||||
addSVGIcon( "actions/quickfixOffBulb.svg" );
|
||||
|
||||
addSVGIcon( "objects/abstractClass.svg" );
|
||||
addSVGIcon( "objects/abstractMethod.svg" );
|
||||
addSVGIcon( "objects/annotationtype.svg" );
|
||||
addSVGIcon( "objects/annotationtype.svg" );
|
||||
addSVGIcon( "objects/css.svg" );
|
||||
addSVGIcon( "objects/javaScript.svg" );
|
||||
addSVGIcon( "objects/xhtml.svg" );
|
||||
|
||||
addSVGIcon( "errorDialog.svg" );
|
||||
addSVGIcon( "informationDialog.svg" );
|
||||
addSVGIcon( "warningDialog.svg" );
|
||||
}
|
||||
|
||||
private void addSVGIcon( String name ) {
|
||||
svgIconsPanel.add( new JLabel( new FlatSVGIcon( "com/formdev/flatlaf/demo/extras/svg/" + name ) ) );
|
||||
}
|
||||
|
||||
private void triStateCheckBox1Changed() {
|
||||
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
label4 = new JLabel();
|
||||
label1 = new JLabel();
|
||||
triStateCheckBox1 = new TriStateCheckBox();
|
||||
triStateLabel1 = new JLabel();
|
||||
label2 = new JLabel();
|
||||
svgIconsPanel = new JPanel();
|
||||
label3 = new JLabel();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
"hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[left]",
|
||||
// rows
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//---- label4 ----
|
||||
label4.setText("Note: Components on this page require the flatlaf-extras library.");
|
||||
add(label4, "cell 0 0 3 1");
|
||||
|
||||
//---- label1 ----
|
||||
label1.setText("TriStateCheckBox:");
|
||||
add(label1, "cell 0 1");
|
||||
|
||||
//---- triStateCheckBox1 ----
|
||||
triStateCheckBox1.setText("three states");
|
||||
triStateCheckBox1.addActionListener(e -> triStateCheckBox1Changed());
|
||||
add(triStateCheckBox1, "cell 1 1");
|
||||
|
||||
//---- triStateLabel1 ----
|
||||
triStateLabel1.setText("text");
|
||||
add(triStateLabel1, "cell 2 1");
|
||||
|
||||
//---- label2 ----
|
||||
label2.setText("SVG Icons:");
|
||||
add(label2, "cell 0 2");
|
||||
|
||||
//======== svgIconsPanel ========
|
||||
{
|
||||
svgIconsPanel.setLayout(new MigLayout(
|
||||
"insets 0,hidemode 3",
|
||||
// columns
|
||||
"[fill]",
|
||||
// rows
|
||||
"[grow,center]"));
|
||||
}
|
||||
add(svgIconsPanel, "cell 1 2 2 1");
|
||||
|
||||
//---- label3 ----
|
||||
label3.setText("The icons may change colors when switching to another theme.");
|
||||
add(label3, "cell 1 3 2 1");
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JLabel label4;
|
||||
private JLabel label1;
|
||||
private TriStateCheckBox triStateCheckBox1;
|
||||
private JLabel triStateLabel1;
|
||||
private JLabel label2;
|
||||
private JPanel svgIconsPanel;
|
||||
private JLabel label3;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
root: new FormRoot {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[][][left]"
|
||||
"$rowConstraints": "[]para[][][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label4"
|
||||
"text": "Note: Components on this page require the flatlaf-extras library."
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label1"
|
||||
"text": "TriStateCheckBox:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1"
|
||||
} )
|
||||
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
|
||||
name: "triStateCheckBox1"
|
||||
"text": "three states"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "triStateCheckBox1Changed", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "triStateLabel1"
|
||||
"text": "text"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label2"
|
||||
"text": "SVG Icons:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3"
|
||||
"$columnConstraints": "[fill]"
|
||||
"$rowConstraints": "[grow,center]"
|
||||
} ) {
|
||||
name: "svgIconsPanel"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"text": "The icons may change colors when switching to another theme."
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 3 2 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 500, 300 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.demo.intellijthemes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
/**
|
||||
* This tool creates look and feel classes for all themes listed in themes.json.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class IJThemesClassGenerator
|
||||
{
|
||||
public static void main( String[] args ) {
|
||||
IJThemesManager themesManager = new IJThemesManager();
|
||||
themesManager.loadBundledThemes();
|
||||
|
||||
String toPath = "../flatlaf-intellij-themes/src/main/java" + IJThemesPanel.THEMES_PACKAGE + "..";
|
||||
|
||||
StringBuilder allInfos = new StringBuilder();
|
||||
StringBuilder markdownTable = new StringBuilder();
|
||||
markdownTable.append( "Name | Class\n" );
|
||||
markdownTable.append( "-----|------\n" );
|
||||
|
||||
for( IJThemeInfo ti : themesManager.bundledThemes ) {
|
||||
if( ti.sourceCodeUrl == null || ti.sourceCodePath == null )
|
||||
continue;
|
||||
|
||||
generateClass( ti, toPath, allInfos, markdownTable );
|
||||
}
|
||||
|
||||
Path out = new File( toPath, "FlatAllIJThemes.java" ).toPath();
|
||||
String allThemes = CLASS_HEADER + ALL_THEMES_TEMPLATE.replace( "${allInfos}", allInfos );
|
||||
writeFile( out, allThemes );
|
||||
|
||||
System.out.println( markdownTable );
|
||||
}
|
||||
|
||||
private static void generateClass( IJThemeInfo ti, String toPath, StringBuilder allInfos, StringBuilder markdownTable ) {
|
||||
String resourceName = ti.resourceName;
|
||||
String resourcePath = null;
|
||||
int resSep = resourceName.indexOf( '/' );
|
||||
if( resSep >= 0 ) {
|
||||
resourcePath = resourceName.substring( 0, resSep );
|
||||
resourceName = resourceName.substring( resSep + 1 );
|
||||
}
|
||||
|
||||
String name = ti.name;
|
||||
int nameSep = name.indexOf( '/' );
|
||||
if( nameSep >= 0 )
|
||||
name = name.substring( nameSep + 1 ).trim();
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for( String n : name.split( " " ) ) {
|
||||
if( n.length() == 0 || n.equals( "-" ) )
|
||||
continue;
|
||||
|
||||
if( Character.isUpperCase( n.charAt( 0 ) ) )
|
||||
buf.append( n );
|
||||
else
|
||||
buf.append( Character.toUpperCase( n.charAt( 0 ) ) ).append( n.substring( 1 ) );
|
||||
}
|
||||
|
||||
String subPackage = (resourcePath != null) ? '.' + resourcePath.replace( "-", "" ) : "";
|
||||
String themeClass = "Flat" + buf + "IJTheme";
|
||||
String themeFile = resourceName;
|
||||
|
||||
String classBody = CLASS_HEADER + CLASS_TEMPLATE
|
||||
.replace( "${subPackage}", subPackage )
|
||||
.replace( "${themeClass}", themeClass )
|
||||
.replace( "${themeFile}", themeFile );
|
||||
|
||||
File toDir = new File( toPath );
|
||||
if( resourcePath != null )
|
||||
toDir = new File( toDir, resourcePath.replace( "-", "" ) );
|
||||
|
||||
Path out = new File( toDir, themeClass + ".java" ).toPath();
|
||||
writeFile( out, classBody );
|
||||
|
||||
if( allInfos.length() > 0 )
|
||||
allInfos.append( '\n' );
|
||||
allInfos.append( THEME_TEMPLATE
|
||||
.replace( "${subPackage}", subPackage )
|
||||
.replace( "${themeClass}", themeClass )
|
||||
.replace( "${themeName}", name ) );
|
||||
|
||||
markdownTable.append( String.format( "[%s](%s) | `com.formdev.flatlaf.intellijthemes%s.%s`\n",
|
||||
name, ti.sourceCodeUrl, subPackage, themeClass ) );
|
||||
}
|
||||
|
||||
private static void writeFile( Path out, String content ) {
|
||||
try {
|
||||
Files.write( out, content.getBytes( StandardCharsets.ISO_8859_1 ),
|
||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CLASS_HEADER =
|
||||
"/*\n" +
|
||||
" * Copyright 2020 FormDev Software GmbH\n" +
|
||||
" *\n" +
|
||||
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
|
||||
" * you may not use this file except in compliance with the License.\n" +
|
||||
" * You may obtain a copy of the License at\n" +
|
||||
" *\n" +
|
||||
" * https://www.apache.org/licenses/LICENSE-2.0\n" +
|
||||
" *\n" +
|
||||
" * Unless required by applicable law or agreed to in writing, software\n" +
|
||||
" * distributed under the License is distributed on an \"AS IS\" BASIS,\n" +
|
||||
" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
|
||||
" * See the License for the specific language governing permissions and\n" +
|
||||
" * limitations under the License.\n" +
|
||||
" */\n" +
|
||||
"\n";
|
||||
|
||||
private static final String CLASS_TEMPLATE =
|
||||
"package com.formdev.flatlaf.intellijthemes${subPackage};\n" +
|
||||
"\n" +
|
||||
"import com.formdev.flatlaf.IntelliJTheme;\n" +
|
||||
"\n" +
|
||||
"/**\n" +
|
||||
" * @author Karl Tauber\n" +
|
||||
" */\n" +
|
||||
"public class ${themeClass}\n" +
|
||||
" extends IntelliJTheme.ThemeLaf\n" +
|
||||
"{\n" +
|
||||
" public static boolean install( ) {\n" +
|
||||
" try {\n" +
|
||||
" return install( new ${themeClass}() );\n" +
|
||||
" } catch( RuntimeException ex ) {\n" +
|
||||
" return false;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public ${themeClass}() {\n" +
|
||||
" super( Utils.loadTheme( \"${themeFile}\" ) );\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
|
||||
private static final String ALL_THEMES_TEMPLATE =
|
||||
"package com.formdev.flatlaf.intellijthemes;\n" +
|
||||
"\n" +
|
||||
"import javax.swing.UIManager.LookAndFeelInfo;\n" +
|
||||
"\n" +
|
||||
"/**\n" +
|
||||
" * @author Karl Tauber\n" +
|
||||
" */\n" +
|
||||
"public class FlatAllIJThemes\n" +
|
||||
"{\n" +
|
||||
" public static final LookAndFeelInfo[] INFOS = {\n" +
|
||||
"${allInfos}\n" +
|
||||
" };\n" +
|
||||
"}\n";
|
||||
|
||||
private static final String THEME_TEMPLATE =
|
||||
" new LookAndFeelInfo( \"${themeName}\", \"com.formdev.flatlaf.intellijthemes${subPackage}.${themeClass}\" ),";
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
@@ -38,7 +37,6 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
@@ -48,6 +46,7 @@ import com.formdev.flatlaf.FlatDarkLaf;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import com.formdev.flatlaf.FlatPropertiesLaf;
|
||||
import com.formdev.flatlaf.IntelliJTheme;
|
||||
import com.formdev.flatlaf.demo.DemoPrefs;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
@@ -60,6 +59,8 @@ import net.miginfocom.swing.*;
|
||||
public class IJThemesPanel
|
||||
extends JPanel
|
||||
{
|
||||
public static final String THEMES_PACKAGE = "/com/formdev/flatlaf/intellijthemes/themes/";
|
||||
|
||||
private final IJThemesManager themesManager = new IJThemesManager();
|
||||
private final List<IJThemeInfo> themes = new ArrayList<>();
|
||||
private final HashMap<Integer, String> categories = new HashMap<>();
|
||||
@@ -196,14 +197,14 @@ public class IJThemesPanel
|
||||
}
|
||||
|
||||
private void themesListValueChanged( ListSelectionEvent e ) {
|
||||
if( e.getValueIsAdjusting() || isAdjustingThemesList )
|
||||
return;
|
||||
|
||||
IJThemeInfo themeInfo = themesList.getSelectedValue();
|
||||
boolean bundledTheme = (themeInfo != null && themeInfo.resourceName != null);
|
||||
saveButton.setEnabled( bundledTheme );
|
||||
sourceCodeButton.setEnabled( bundledTheme );
|
||||
|
||||
if( e.getValueIsAdjusting() || isAdjustingThemesList )
|
||||
return;
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
setTheme( themeInfo );
|
||||
} );
|
||||
@@ -227,7 +228,7 @@ public class IJThemesPanel
|
||||
} else if( themeInfo.themeFile != null ) {
|
||||
try {
|
||||
if( themeInfo.themeFile.getName().endsWith( ".properties" ) ) {
|
||||
FlatLaf.install( new PropertiesLaf( themeInfo.name, themeInfo.themeFile ) );
|
||||
FlatLaf.install( new FlatPropertiesLaf( themeInfo.name, themeInfo.themeFile ) );
|
||||
} else
|
||||
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( themeInfo.themeFile ) ) );
|
||||
|
||||
@@ -237,7 +238,7 @@ public class IJThemesPanel
|
||||
showInformationDialog( "Failed to load '" + themeInfo.themeFile + "'.", ex );
|
||||
}
|
||||
} else {
|
||||
IntelliJTheme.install( getClass().getResourceAsStream( themeInfo.resourceName ) );
|
||||
IntelliJTheme.install( getClass().getResourceAsStream( THEMES_PACKAGE + themeInfo.resourceName ) );
|
||||
DemoPrefs.getState().put( DemoPrefs.KEY_LAF_THEME, DemoPrefs.RESOURCE_PREFIX + themeInfo.resourceName );
|
||||
}
|
||||
|
||||
@@ -260,7 +261,7 @@ public class IJThemesPanel
|
||||
|
||||
// save theme
|
||||
try {
|
||||
Files.copy( getClass().getResourceAsStream( themeInfo.resourceName ),
|
||||
Files.copy( getClass().getResourceAsStream( THEMES_PACKAGE + themeInfo.resourceName ),
|
||||
file.toPath(), StandardCopyOption.REPLACE_EXISTING );
|
||||
} catch( IOException ex ) {
|
||||
showInformationDialog( "Failed to save theme to '" + file + "'.", ex );
|
||||
@@ -273,7 +274,7 @@ public class IJThemesPanel
|
||||
File licenseFile = new File( file.getParentFile(),
|
||||
StringUtils.removeTrailing( file.getName(), ".theme.json" ) +
|
||||
themeInfo.licenseFile.substring( themeInfo.licenseFile.indexOf( '.' ) ) );
|
||||
Files.copy( getClass().getResourceAsStream( themeInfo.licenseFile ),
|
||||
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 );
|
||||
@@ -340,7 +341,7 @@ public class IJThemesPanel
|
||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||
String theme = UIManager.getLookAndFeelDefaults().getString( DemoPrefs.THEME_UI_KEY );
|
||||
|
||||
if( theme == null && (lookAndFeel instanceof IntelliJTheme.ThemeLaf || lookAndFeel instanceof PropertiesLaf) )
|
||||
if( theme == null && (lookAndFeel instanceof IntelliJTheme.ThemeLaf || lookAndFeel instanceof FlatPropertiesLaf) )
|
||||
return;
|
||||
|
||||
Predicate<IJThemeInfo> test;
|
||||
@@ -429,78 +430,4 @@ public class IJThemesPanel
|
||||
private JScrollPane themesScrollPane;
|
||||
private JList<IJThemeInfo> themesList;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class PropertiesLaf ------------------------------------------------
|
||||
|
||||
public static class PropertiesLaf
|
||||
extends FlatLaf
|
||||
{
|
||||
private final String name;
|
||||
private final String baseTheme;
|
||||
private final boolean dark;
|
||||
private final Properties properties;
|
||||
|
||||
public PropertiesLaf( String name, File propertiesFile )
|
||||
throws IOException
|
||||
{
|
||||
this.name = name;
|
||||
|
||||
properties = new Properties();
|
||||
try( InputStream in = new FileInputStream( propertiesFile ) ) {
|
||||
if( in != null )
|
||||
properties.load( in );
|
||||
}
|
||||
|
||||
baseTheme = properties.getProperty( "@baseTheme", "light" );
|
||||
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDark() {
|
||||
return dark;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
lafClasses.add( FlatLaf.class );
|
||||
switch( baseTheme.toLowerCase() ) {
|
||||
default:
|
||||
case "light":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
break;
|
||||
|
||||
case "dark":
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
break;
|
||||
|
||||
case "intellij":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
lafClasses.add( FlatIntelliJLaf.class );
|
||||
break;
|
||||
|
||||
case "darcula":
|
||||
lafClasses.add( FlatDarkLaf.class );
|
||||
lafClasses.add( FlatDarculaLaf.class );
|
||||
break;
|
||||
}
|
||||
lafClasses.add( PropertiesLaf.class );
|
||||
return lafClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties getAdditionalDefaults() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class IJThemesUpdater
|
||||
else if( fromUrl.contains( "gitlab.com" ) )
|
||||
fromUrl = fromUrl.replace( "/blob/", "/raw/" );
|
||||
|
||||
String toPath = "src/main/resources/com/formdev/flatlaf/demo/intellijthemes/" + ti.resourceName;
|
||||
String toPath = "../flatlaf-intellij-themes/src/main/resources" + IJThemesPanel.THEMES_PACKAGE + ti.resourceName;
|
||||
|
||||
download( fromUrl, toPath );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
The icons in this folder are from IntelliJ IDEA Community Edition,
|
||||
which is licensed under the Apache 2.0 license. Copyright 2000-2019 JetBrains s.r.o.
|
||||
See: https://github.com/JetBrains/intellij-community/
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd" transform="translate(2 2)">
|
||||
<rect width="5.5" height="5.5" fill="#59A869"/>
|
||||
<rect width="5.5" height="5.5" x="6.5" fill="#EDA200"/>
|
||||
<rect width="5.5" height="5.5" y="6.5" fill="#389FD6"/>
|
||||
<rect width="5.5" height="5.5" x="6.5" y="6.5" fill="#DB5860"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 403 B |
@@ -1,6 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#AFB1B3" d="M11,3 L4,3 L4,11 L2,11 L2,1 L11,1 L11,3 Z"/>
|
||||
<path fill="#AFB1B3" d="M5,4 L14,4 L14,14 L5,14 L5,4 Z M7,6 L7,7 L12,7 L12,6 L7,6 Z M7,10 L7,11 L12,11 L12,10 L7,10 Z M7,8 L7,9 L12,9 L12,8 L7,8 Z"/>
|
||||
<path fill="#6E6E6E" d="M11,3 L4,3 L4,11 L2,11 L2,1 L11,1 L11,3 Z"/>
|
||||
<path fill="#6E6E6E" d="M5,4 L14,4 L14,14 L5,14 L5,4 Z M7,6 L7,7 L12,7 L12,6 L7,6 Z M7,10 L7,11 L12,11 L12,10 L7,10 Z M7,8 L7,9 L12,9 L12,8 L7,8 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<polygon fill="#59A869" fill-rule="evenodd" points="4 2 14 8 4 14"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 162 B |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="6" height="1" x="5" y="12" fill="#6E6E6E"/>
|
||||
<path fill="#6E6E6E" d="M5.5,14 L10.5,14 L10.5,14 C10.5,14.5522847 10.0522847,15 9.5,15 L6.5,15 C5.94771525,15 5.5,14.5522847 5.5,14 Z"/>
|
||||
<path fill="#EDA200" d="M13,5.2 C13,9.2 11,8.96875 11,11 L5,11 C5,9.03125 3,9.2 3,5.2 C3,2.991 5.23878906,1 8,1 C10.76125,1 13,2.99103125 13,5.2 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 493 B |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="6" height="1" x="5" y="12" fill="#6E6E6E"/>
|
||||
<path fill="#6E6E6E" d="M5.5,14 L10.5,14 L10.5,14 C10.5,14.5522847 10.0522847,15 9.5,15 L6.5,15 C5.94771525,15 5.5,14.5522847 5.5,14 Z"/>
|
||||
<path fill="#389FD6" d="M13,5.2 C13,9.2 11,8.96875 11,11 L5,11 C5,9.03125 3,9.2 3,5.2 C3,2.991 5.23878906,1 8,1 C10.76125,1 13,2.99103125 13,5.2 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 493 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<rect width="10" height="10" x="3" y="3" fill="#DB5860" fill-rule="evenodd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 171 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#DB5860" fill-rule="evenodd" d="M16,30 C8.2680135,30 2,23.7319865 2,16 C2,8.2680135 8.2680135,2 16,2 C23.7319865,2 30,8.2680135 30,16 C30,23.7319865 23.7319865,30 16,30 Z M14,7 L14,18 L18,18 L18,7 L14,7 Z M14,21 L14,25 L18,25 L18,21 L14,21 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 350 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#389FD6" fill-rule="evenodd" d="M16,30 C8.2680135,30 2,23.7319865 2,16 C2,8.2680135 8.2680135,2 16,2 C23.7319865,2 30,8.2680135 30,16 C30,23.7319865 23.7319865,30 16,30 Z M14,7 L14,18 L18,18 L18,7 L14,7 Z M14,21 L14,25 L18,25 L18,21 L14,21 Z" transform="rotate(180 16 16)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 380 B |
@@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<rect id="abstractclass-a" width="8" height="14"/>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#9AA7B0" fill-opacity=".8" d="M3 3.1055C1.764 4.3685 1 6.0935 1 8.0005 1 9.9065 1.764 11.6315 3 12.8945L3 3.1055zM13 3.1055L13 12.8945C14.236 11.6315 15 9.9065 15 8.0005 15 6.0935 14.236 4.3675 13 3.1055"/>
|
||||
<g transform="translate(4 1)">
|
||||
<mask id="abstractclass-b" fill="#fff">
|
||||
<use xlink:href="#abstractclass-a"/>
|
||||
</mask>
|
||||
<g mask="url(#abstractclass-b)">
|
||||
<g transform="translate(-4 -1)">
|
||||
<path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/>
|
||||
<path fill="#231F20" fill-opacity=".7" d="M5,4.28253174 C4.53,4.74153174 4.028,4.978 3.1,5 C2.061,5.022 1,4.2794 1,3.0004 C1,1.7124 1.971,1 3.1,1 C3.94833171,1 4.54833171,1.18475342 4.9,1.55426025 L5.5162,0.836730957 C4.8293999,0.270175195 4.28826904,0.0004 3.0982,0.0004 C1.3402,0.0004 0.0002,1.3584 0.0002,3.0004 C0.0002,4.6824 1.3642,6.0004 3.0022,6.0004 C4.29284668,6.0004 5.0232,5.5934 5.6162,4.9814 C5.2054,4.51548783 5,4.28253174 5,4.28253174 Z" transform="translate(5 5)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<rect id="abstractmethod-a" width="8" height="14"/>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#9AA7B0" fill-opacity=".8" d="M3 3.1055C1.764 4.3685 1 6.0935 1 8.0005 1 9.9065 1.764 11.6315 3 12.8945L3 3.1055zM13 3.1055L13 12.8945C14.236 11.6315 15 9.9065 15 8.0005 15 6.0935 14.236 4.3675 13 3.1055"/>
|
||||
<g transform="translate(4 1)">
|
||||
<mask id="abstractmethod-b" fill="#fff">
|
||||
<use xlink:href="#abstractmethod-a"/>
|
||||
</mask>
|
||||
<g mask="url(#abstractmethod-b)">
|
||||
<g transform="translate(-4 -1)">
|
||||
<path fill="#F98B9E" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/>
|
||||
<path fill="#231F20" fill-opacity=".7" d="M6.9922,2 C6.9912,1.251 6.63513184,0.0003 4.98162842,0.0003 C4.11224365,0.0003 3.6576,0.502 3.5986,0.6 C3.28363037,0.194116211 2.94411621,0.0003 2.1,0.0003 C1.63194173,0.0003 1.26527507,0.0999436667 1,0.299231 L1,0.0003 L0,0.0003 L0,5.0003 L1,5.0003 C0.966666667,3.1563 0.966666667,2.1562 1,2 C1.05,1.7657 1.05,1 2,1 C2.95,1 2.999,1.537 3,2 L3,5.0003 L4,5.0003 L4,2 C4,1.686 3.95911952,1 4.98162842,1 C6.00413731,1 6.00413731,1.73961181 6.00469971,2 C6.00469971,2.79041884 6.00469971,3.38323296 6.00469971,3.77844238 C6.00469971,4.0499663 6.00469971,4.45725217 6.00469971,5.0003 L6.9972,5.0003 L6.9922,2 Z" transform="translate(5 6)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#62B543" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/>
|
||||
<path fill="#231F20" fill-opacity=".7" d="M3.6281,2.7611 C3.4731,2.8511 3.3451,2.9741 3.2461,3.1241 C3.1511,3.2721 3.0811,3.4411 3.0391,3.6261 C2.9971,3.8091 2.9761,3.9961 2.9761,4.1841 C2.9761,4.5861 3.0491,4.8721 3.1971,5.0581 C3.3491,5.2481 3.5541,5.3451 3.8051,5.3451 C3.9701,5.3451 4.1151,5.3071 4.2371,5.2311 C4.3571,5.1581 4.4571,5.0531 4.5331,4.9201 C4.6061,4.7931 4.6631,4.6401 4.7011,4.4641 C4.7391,4.2941 4.7641,4.1011 4.7731,3.8931 L4.8421,2.6991 L4.8001,2.6891 C4.6851,2.6621 4.5981,2.6481 4.5001,2.6371 C4.4021,2.6271 4.3041,2.6221 4.2021,2.6221 C3.9781,2.6221 3.7861,2.6681 3.6281,2.7611 Z M0.0021,4.0006 C0.0021,0.0011 3.66741943,0.0011 4.3161,0.0011 C4.65105644,0.0011 8.0001,0.0864290039 8.0001,3.5571 C8.0001,6.0091 6.4751,6 6.1701,6 C5.67331784,5.97 5.31431784,5.7737 5.0931,5.4111 C4.68260397,5.8037 4.28127064,6 3.8891,6 C3.0796519,6 2.0001,5.9211 2.0001,4.0001 C2.0001,2.32043457 3.45593262,2.0001 4.0001,2.0001 C4.1531,2.0001 5.7451,2.0551 5.8241,2.0791 L5.7441,4.1881 C5.6361,4.89276667 5.7991,5.2451 6.2331,5.2451 C6.95605469,5.2451 7.0601,3.7831 7.0601,3.5471 C7.0601,0.907409668 4.7081,0.7451 4.3161,0.7451 C3.7711,0.7451 0.94354248,0.850891113 0.94354248,4.0006 C0.94354248,4.58402311 0.94354248,7.2461 3.8891,7.2461 C4.0901,7.2461 5.7441,7.04302979 6.1621,6.8281 L6.1621,7.5781 C5.8551,7.7031 5.0931,8.0001 3.8981,8.0001 C3.15576172,8.0001 0.0021,8.0001 0.0021,4.0006 Z" transform="translate(4 4)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |