Compare commits

...

43 Commits
0.11 ... 0.15

Author SHA1 Message Date
Karl Tauber
be88eeb343 release 0.15 2019-10-21 18:29:40 +02:00
Karl Tauber
342b932f9e ToolTip:
- Improved styling of dark tooltips (darker background, no border).
- increased top and bottom margins
- use brighter color in light theme
- Fixed colors in tooltips of disabled components. (issue #15)
2019-10-21 18:07:43 +02:00
Karl Tauber
964dc14a8a ComboBox: fixed NPE in combobox with custom renderer after switching to FlatLaf (#16; regression in 0.14) 2019-10-21 17:04:23 +02:00
Karl Tauber
b56f462626 SwingX: added screenshots 2019-10-21 13:42:22 +02:00
Karl Tauber
4477b4c44e release 0.14 2019-10-21 10:52:33 +02:00
Karl Tauber
714c6e2920 TextField and PasswordField: fixed minimum width if focusWidth > 2 and not having a FlatBorder 2019-10-20 22:17:15 +02:00
Karl Tauber
0853a1aa2e SwingX: fixed preferred width of JXDatePicker, which was too large (#8) 2019-10-20 22:16:13 +02:00
Karl Tauber
f9d2312b3a ComboBox: fixed StackOverflowError when switching LaF (#14) 2019-10-20 20:04:10 +02:00
Karl Tauber
f53f205f52 SwingX: fixed JXDatePicker.TodayPanel colors (#8) 2019-10-20 18:18:06 +02:00
Karl Tauber
41ecbccc76 EditorPane and TextPane: fixed font and text color when using HTML content (#9) 2019-10-20 18:17:47 +02:00
Karl Tauber
5a952c187c SwingX: JXMonthView support (#8) 2019-10-20 10:47:53 +02:00
Karl Tauber
0a86d00c1e FlatLaf: allow specifying value type in value for cases where auto-detecting value type from key or value does not work 2019-10-19 13:47:53 +02:00
Karl Tauber
b3e9d82537 SwingX: added SwingX LaF addon (#8) 2019-10-19 09:36:43 +02:00
Karl Tauber
0970dceee2 SwingX: JXDatePicker support (#8) 2019-10-19 09:35:01 +02:00
Karl Tauber
ffef71d6db OptionPane: fixed rendering of longer HTML text (#12) 2019-10-18 18:41:14 +02:00
Karl Tauber
0ede8cd5b9 SwingX: build.gradle.kts: added maven publishing and bintray upload 2019-10-18 14:36:04 +02:00
Karl Tauber
c1a9f48e6b SwingX: JXBusyLabel support (#8) 2019-10-18 13:26:30 +02:00
Karl Tauber
3f7215c602 update to Gradle 5.6.3
./gradlew wrapper --gradle-version=5.6.3
2019-10-18 10:34:39 +02:00
Karl Tauber
8b5e3e344a SwingX: JXHeader support (#8) 2019-10-18 10:33:05 +02:00
Karl Tauber
212ff012d6 SwingX: JXTaskPaneContainer and JXTaskPane support (#8) 2019-10-18 10:31:24 +02:00
Karl Tauber
7c77b857f6 SwingX: added test app 2019-10-17 12:09:22 +02:00
Karl Tauber
423c01074a SwingX: flatlaf-swingx subproject created; JXHyperlink support (#8) 2019-10-17 11:21:23 +02:00
Karl Tauber
2dbd584e28 use KeyEventPostProcessor instead of AWTEventListener for listening for Alt key pressed (similar to WindowLookAndFeel) (#4) 2019-10-16 19:42:55 +02:00
Karl Tauber
250f435ceb build.gradle.kts: moved jcenter to root script 2019-10-16 19:39:41 +02:00
Karl Tauber
fa4e409555 ToolBar: disable focusability of buttons in toolbar 2019-10-15 19:00:51 +02:00
Karl Tauber
dfc3b7c796 README.md: intro updated 2019-10-15 11:40:19 +02:00
Karl Tauber
41df9859ad ComboBox: use small border if used as table editor 2019-10-15 10:41:28 +02:00
Karl Tauber
a8b8cbdf8c FlatTestFrame: reduced duplicate code 2019-10-14 17:55:38 +02:00
Karl Tauber
fe2909c56a Demo: build.gradle.kts: added bintray upload 2019-10-14 10:59:45 +02:00
Karl Tauber
3a2fe06c34 README.md: added Maven Central coordinates 2019-10-13 22:54:41 +02:00
Karl Tauber
873e8604ce added developer information to Maven POM for Maven Central publishing 2019-10-13 21:37:49 +02:00
Karl Tauber
2cfcd0facf release 0.12 2019-10-13 17:53:36 +02:00
Karl Tauber
b49eff348d Linux: support KDE (#2)
The Swing fonts are not updated when the user changes system font size (System Settings > Fonts > Force Font DPI). A application restart is necessary. This is the same behavior as in native KDE applications.

tested on Kubuntu 19.04
2019-10-13 17:48:46 +02:00
Karl Tauber
42d801f123 Linux:
- allow user scaling mode on Linux even if running in Java 9+
- update fonts (and scaling) when user changes text size or scaling in Gnome settings

(#1)
2019-10-13 14:15:37 +02:00
Karl Tauber
5e33182de3 Windows: update fonts (and scaling) when user changes Windows text size 2019-10-12 20:14:18 +02:00
Karl Tauber
012d86066d UI inspector: fixed NPE and use anti-aliasing for painting line border on Java 9+ for better results when scaled 2019-10-12 13:43:43 +02:00
Karl Tauber
ff510095a3 UIScale: renamed some methods (to avoid confusion) 2019-10-12 13:42:05 +02:00
Karl Tauber
10283d022f Linux: initialize font (#2) 2019-10-12 10:44:11 +02:00
Karl Tauber
d55abd1b00 README.md: use SVG button for demo download 2019-10-10 11:15:19 +02:00
Karl Tauber
87845fc6f5 added Flat*Laf.install() methods 2019-10-10 10:34:40 +02:00
Karl Tauber
340c0d647c README.md: temporary removed jcenter coordinates because they currently do not work 2019-10-09 11:56:29 +02:00
Karl Tauber
49a574a8d7 macOS: use native screen menu bar if system property apple.laf.useScreenMenuBar is true 2019-10-08 23:41:51 +02:00
Karl Tauber
9216997bba screenshots updated 2019-10-08 23:32:26 +02:00
65 changed files with 3048 additions and 219 deletions

View File

@@ -1,6 +1,41 @@
FlatLaf Change Log FlatLaf Change Log
================== ==================
## 0.15
- ToolTip: Improved styling of dark tooltips (darker background, no border).
- ToolTip: Fixed colors in tooltips of disabled components. (issue #15)
- ComboBox: Fixed NPE in combobox with custom renderer after switching to
FlatLaf. (issue #16; regression in 0.14)
## 0.14
- ComboBox: Use small border if used as table editor.
- ToolBar: Disable focusability of buttons in toolbar.
- OptionPane: Fixed rendering of longer HTML text. (issue #12)
- EditorPane and TextPane: Fixed font and text color when using HTML content.
(issue #9)
- ComboBox: Fixed `StackOverflowError` when switching LaF. (issue #14)
- SwingX: Support `JXBusyLabel`, `JXDatePicker`, `JXHeader`, `JXHyperlink`,
`JXMonthView`, `JXTaskPaneContainer` and `JXTaskPane`. (issue #8)
## 0.13
- Added developer information to Maven POM for Maven Central publishing.
## 0.12
- Support Linux. (issue #2)
- Added `Flat*Laf.install()` methods.
- macOS: Use native screen menu bar if system property
`apple.laf.useScreenMenuBar` is `true`.
- Windows: Update fonts (and scaling) when user changes Windows text size
(Settings > Ease of Access > Display > Make text bigger).
## 0.11 ## 0.11
- Changed Maven groupId to `com.formdev` and artifactId to `flatlaf`. - Changed Maven groupId to `com.formdev` and artifactId to `flatlaf`.

View File

@@ -1,15 +1,15 @@
FlatLaf - Flat Look and Feel FlatLaf - Flat Look and Feel
============================ ============================
**FlatLaf** is a modern open-source cross-platform Look and Feel for Java **FlatLaf** is a modern **open-source** cross-platform Look and Feel for Java
desktop applications. Swing desktop applications.
It looks mostly "flat" (no shadows or gradients), clean, simple and elegant. It looks almost flat (no shadows or gradients), clean, simple and elegant.
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes, FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
scales on **HiDPI** displays and runs on Java 8 or newer. scales on **HiDPI** displays and runs on Java 8 or newer.
The look is heavily inspired by **Darcula** and **IntelliJ** themes from The look is heavily inspired by **Darcula** and **IntelliJ** themes from
IntelliJ IDEA 2019.2+ and uses mostly the same colors and icons. IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
![Flat Light Demo](images/FlatLightDemo.png) ![Flat Light Demo](images/FlatLightDemo.png)
@@ -19,26 +19,37 @@ IntelliJ IDEA 2019.2+ and uses mostly the same colors and icons.
Demo Demo
---- ----
Download [![Download Demo](https://download.formdev.com/flatlaf/images/download-demo.svg)](https://download.formdev.com/flatlaf/flatlaf-demo-latest.jar)
[flatlaf-demo-0.11.jar](https://download.formdev.com/flatlaf/flatlaf-demo-0.11.jar)
and run it with `java -jar flatlaf-demo-0.11.jar` (or double-click it). Requires Run demo with `java -jar flatlaf-demo-<version>.jar` (or double-click it).
Java 8 or newer. Requires Java 8 or newer.
Download Download
-------- --------
FlatLaf binaries are available on **JCenter** and **Maven Central**.
If you use Maven or Gradle, add a dependency with following coordinates to your
build script:
groupId: com.formdev
artifactId: flatlaf
version: 0.15
Otherwise download `flatlaf-<version>.jar` here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion) [![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)
For Maven or Gradle use:
Repository: jcenter (https://jcenter.bintray.com/) Addons
Group Id: com.formdev ------
Artifact Id: flatlaf
Version: 0.11 - [SwingX](flatlaf-swingx)
License Documentation
------- -------------
FlatLaf is open source licensed under the [Apache 2.0 License](LICENSE) For more information and documentation visit
[FlatLaf Home](https://www.formdev.com/flatlaf/)

View File

@@ -14,7 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
version = "0.11" version = "0.15"
allprojects {
repositories {
jcenter()
}
}
// check required Java version // check required Java version
if( JavaVersion.current() < JavaVersion.VERSION_1_8 ) if( JavaVersion.current() < JavaVersion.VERSION_1_8 )

View File

@@ -22,10 +22,6 @@ plugins {
id( "com.jfrog.bintray" ) version "1.8.4" id( "com.jfrog.bintray" ) version "1.8.4"
} }
repositories {
jcenter()
}
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) { if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
sourceSets { sourceSets {
create( "module-info" ) { create( "module-info" ) {
@@ -92,6 +88,19 @@ tasks {
from( javadoc ) from( javadoc )
} }
register( "testJar", Jar::class ) {
archiveBaseName.set( "flatlaf-test" )
from( sourceSets.test.get().output )
}
}
configurations {
create( "testArtifacts" )
}
artifacts {
add( "testArtifacts", tasks.getByPath( "testJar" ) )
} }
publishing { publishing {
@@ -117,6 +126,14 @@ publishing {
} }
} }
developers {
developer {
name.set( "Karl Tauber" )
organization.set( "FormDev Software GmbH" )
organizationUrl.set( "https://www.formdev.com/" )
}
}
scm { scm {
url.set( "https://github.com/JFormDesigner/FlatLaf" ) url.set( "https://github.com/JFormDesigner/FlatLaf" )
} }

View File

@@ -24,6 +24,10 @@ package com.formdev.flatlaf;
public class FlatDarculaLaf public class FlatDarculaLaf
extends FlatDarkLaf extends FlatDarkLaf
{ {
public static boolean install( ) {
return install( new FlatDarculaLaf() );
}
@Override @Override
public String getName() { public String getName() {
return "Flat Darcula"; return "Flat Darcula";

View File

@@ -24,6 +24,10 @@ package com.formdev.flatlaf;
public class FlatDarkLaf public class FlatDarkLaf
extends FlatLaf extends FlatLaf
{ {
public static boolean install( ) {
return install( new FlatDarkLaf() );
}
@Override @Override
public String getName() { public String getName() {
return "Flat Dark"; return "Flat Dark";

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf;
import java.io.InputStream;
/**
* Addon for FlatLaf UI defaults.
*
* Allows loading of additional .properties files from addon JARs.
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
*
* If you extend this class in a addon JAR, you also have to add a text file named
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
* to the addon JAR. The file must contain a single line with the class name.
*
* See 'flatlaf-swingx' addon for an example
*
* @author Karl Tauber
*/
public abstract class FlatDefaultsAddon
{
/**
* Finds an addon .properties file for the given LaF class and returns
* it as input stream. Or {@code null} if not found.
*/
public abstract InputStream getDefaults( Class<?> lafClass );
}

View File

@@ -24,6 +24,10 @@ package com.formdev.flatlaf;
public class FlatIntelliJLaf public class FlatIntelliJLaf
extends FlatLightLaf extends FlatLightLaf
{ {
public static boolean install( ) {
return install( new FlatIntelliJLaf() );
}
@Override @Override
public String getName() { public String getName() {
return "Flat IntelliJ"; return "Flat IntelliJ";

View File

@@ -16,32 +16,38 @@
package com.formdev.flatlaf; package com.formdev.flatlaf;
import java.awt.AWTEvent;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.Insets; import java.awt.Insets;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.Window; import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function; import java.util.function.Function;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIDefaults.LazyValue; import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource; import javax.swing.plaf.DimensionUIResource;
@@ -63,6 +69,8 @@ import com.formdev.flatlaf.util.UIScale;
public abstract class FlatLaf public abstract class FlatLaf
extends BasicLookAndFeel extends BasicLookAndFeel
{ {
private static final String TYPE_PREFIX = "{";
private static final String TYPE_PREFIX_END = "}";
private static final String VARIABLE_PREFIX = "@"; private static final String VARIABLE_PREFIX = "@";
private static final String REF_PREFIX = VARIABLE_PREFIX + "@"; private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?"; private static final String OPTIONAL_PREFIX = "?";
@@ -70,9 +78,22 @@ public abstract class FlatLaf
private BasicLookAndFeel base; private BasicLookAndFeel base;
private AWTEventListener mnemonicListener; private String desktopPropertyName;
private PropertyChangeListener desktopPropertyListener;
private KeyEventPostProcessor mnemonicListener;
private static boolean altKeyPressed; private static boolean altKeyPressed;
public static boolean install( LookAndFeel newLookAndFeel ) {
try {
UIManager.setLookAndFeel( newLookAndFeel );
return true;
} catch( Exception ex ) {
System.err.println( "Failed to initialize look and feel " + newLookAndFeel.getClass().getName() );
return false;
}
}
@Override @Override
public String getID() { public String getID() {
return getName(); return getName();
@@ -96,17 +117,43 @@ public abstract class FlatLaf
// add mnemonic listener // add mnemonic listener
mnemonicListener = e -> { mnemonicListener = e -> {
if( e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT ) if( e.getKeyCode() == KeyEvent.VK_ALT )
altKeyChanged( e.getID() == KeyEvent.KEY_PRESSED ); altKeyChanged( e.getID() == KeyEvent.KEY_PRESSED );
return false;
}; };
Toolkit.getDefaultToolkit().addAWTEventListener( mnemonicListener, AWTEvent.KEY_EVENT_MASK ); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( mnemonicListener );
// listen to desktop property changes to update UI if system font or scaling changes
if( SystemInfo.IS_WINDOWS ) {
// Windows 10 allows increasing font size independent of scaling:
// Settings > Ease of Access > Display > Make text bigger (100% - 225%)
desktopPropertyName = "win.messagebox.font";
} else if( SystemInfo.IS_LINUX ) {
// Linux/Gnome allows extra scaling and larger text:
// Settings > Devices > Displays > Scale (100% or 200%)
// Settings > Universal access > Large Text (off or on, 125%)
desktopPropertyName = "gnome.Xft/DPI";
}
if( desktopPropertyName != null ) {
desktopPropertyListener = e -> {
reSetLookAndFeel();
};
Toolkit.getDefaultToolkit().addPropertyChangeListener( desktopPropertyName, desktopPropertyListener );
}
} }
@Override @Override
public void uninitialize() { public void uninitialize() {
// remove desktop property listener
if( desktopPropertyListener != null ) {
Toolkit.getDefaultToolkit().removePropertyChangeListener( desktopPropertyName, desktopPropertyListener );
desktopPropertyName = null;
desktopPropertyListener = null;
}
// remove mnemonic listener // remove mnemonic listener
if( mnemonicListener != null ) { if( mnemonicListener != null ) {
Toolkit.getDefaultToolkit().removeAWTEventListener( mnemonicListener ); KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor( mnemonicListener );
mnemonicListener = null; mnemonicListener = null;
} }
@@ -157,9 +204,17 @@ public abstract class FlatLaf
defaults.put( "Spinner.disabledBackground", control ); defaults.put( "Spinner.disabledBackground", control );
defaults.put( "Spinner.disabledForeground", control ); defaults.put( "Spinner.disabledForeground", control );
// remember MenuBarUI from Mac Aqua LaF if Mac screen menubar is enabled
boolean useScreenMenuBar = SystemInfo.IS_MAC && "true".equals( System.getProperty( "apple.laf.useScreenMenuBar" ) );
Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null;
initFonts( defaults ); initFonts( defaults );
loadDefaultsFromProperties( defaults ); loadDefaultsFromProperties( defaults );
// use Aqua MenuBarUI if Mac screen menubar is enabled
if( useScreenMenuBar )
defaults.put( "MenuBarUI", aquaMenuBarUI );
return defaults; return defaults;
} }
@@ -182,7 +237,8 @@ public abstract class FlatLaf
uiFont = (font instanceof FontUIResource) ? (FontUIResource) font : new FontUIResource( font ); uiFont = (font instanceof FontUIResource) ? (FontUIResource) font : new FontUIResource( font );
} else if( SystemInfo.IS_LINUX ) { } else if( SystemInfo.IS_LINUX ) {
System.err.println( "WARNING: FlatLaf is not yet tested on Linux!" ); Font font = LinuxFontPolicy.getFont();
uiFont = (font instanceof FontUIResource) ? (FontUIResource) font : new FontUIResource( font );
} }
if( uiFont == null ) if( uiFont == null )
@@ -220,12 +276,22 @@ public abstract class FlatLaf
try { try {
// load properties files // load properties files
Properties properties = new Properties(); Properties properties = new Properties();
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
for( Class<?> lafClass : lafClasses ) { for( Class<?> lafClass : lafClasses ) {
// load core properties
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties"; String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) { try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null ) if( in != null )
properties.load( in ); properties.load( in );
} }
// load properties from addons
for( FlatDefaultsAddon addon : addonLoader ) {
try( InputStream in = addon.getDefaults( lafClass ) ) {
if( in != null )
properties.load( in );
}
}
} }
Function<String, String> resolver = value -> { Function<String, String> resolver = value -> {
@@ -293,6 +359,8 @@ public abstract class FlatLaf
return resolveValue( properties, newValue ); return resolveValue( properties, newValue );
} }
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDNUMBER }
private Object parseValue( String key, String value, Function<String, String> resolver ) { private Object parseValue( String key, String value, Function<String, String> resolver ) {
value = value.trim(); value = value.trim();
@@ -303,32 +371,51 @@ public abstract class FlatLaf
case "true": return true; case "true": return true;
} }
// borders ValueType valueType = ValueType.UNKNOWN;
// check whether value type is specified in the value
if( value.startsWith( TYPE_PREFIX ) ) {
int end = value.indexOf( TYPE_PREFIX_END );
if( end != -1 ) {
try {
String typeStr = value.substring( TYPE_PREFIX.length(), end );
valueType = ValueType.valueOf( typeStr.toUpperCase( Locale.ENGLISH ) );
// remove type from value
value = value.substring( end + TYPE_PREFIX_END.length() );
} catch( IllegalArgumentException ex ) {
// ignore
}
}
}
// determine value type from key
if( valueType == ValueType.UNKNOWN ) {
if( key.endsWith( ".border" ) || key.endsWith( "Border" ) ) if( key.endsWith( ".border" ) || key.endsWith( "Border" ) )
return parseBorder( value, resolver ); valueType = ValueType.BORDER;
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
// icons valueType = ValueType.ICON;
if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) ) else if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
return parseInstance( value );
// insets
if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) ) key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
return parseInsets( value ); valueType = ValueType.INSETS;
else if( key.endsWith( "Size" ) )
// scaled number valueType = ValueType.SIZE;
ScaledNumber scaledNumber = parseScaledNumber( key, value ); else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
if( scaledNumber != null ) valueType = ValueType.INTEGER;
return scaledNumber; }
// size
if( key.endsWith( "Size" ) && !key.equals( "SplitPane.dividerSize" ))
return parseSize( value );
// width, height
if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
return parseInteger( value, true );
// parse value
switch( valueType ) {
case STRING: return value;
case INTEGER: return parseInteger( value, true );
case BORDER: return parseBorder( value, resolver );
case ICON: return parseInstance( value );
case INSETS: return parseInsets( value );
case SIZE: return parseSize( value );
case COLOR: return parseColor( value, true );
case SCALEDNUMBER: return parseScaledNumber( value );
case UNKNOWN:
default:
// colors // colors
ColorUIResource color = parseColor( value, false ); ColorUIResource color = parseColor( value, false );
if( color != null ) if( color != null )
@@ -342,6 +429,7 @@ public abstract class FlatLaf
// string // string
return value; return value;
} }
}
private Object parseBorder( String value, Function<String, String> resolver ) { private Object parseBorder( String value, Function<String, String> resolver ) {
if( value.indexOf( ',' ) >= 0 ) { if( value.indexOf( ',' ) >= 0 ) {
@@ -430,12 +518,7 @@ public abstract class FlatLaf
return null; return null;
} }
private ScaledNumber parseScaledNumber( String key, String value ) { private ScaledNumber parseScaledNumber( String value ) {
if( !key.equals( "OptionPane.buttonMinimumWidth" ) &&
!key.equals( "SplitPane.oneTouchButtonSize" ) &&
!key.equals( "SplitPane.oneTouchButtonOffset" ) )
return null; // not supported
try { try {
return new ScaledNumber( Integer.parseInt( value ) ); return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) { } catch( NumberFormatException ex ) {
@@ -458,6 +541,35 @@ public abstract class FlatLaf
return strs; return strs;
} }
private static void reSetLookAndFeel() {
EventQueue.invokeLater( () -> {
try {
// re-set current LaF
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
UIManager.setLookAndFeel( lookAndFeel );
// must fire property change events ourself because old and new LaF are the same
PropertyChangeEvent e = new PropertyChangeEvent( UIManager.class, "lookAndFeel", lookAndFeel, lookAndFeel );
for( PropertyChangeListener l : UIManager.getPropertyChangeListeners() )
l.propertyChange( e );
// update UI
updateUI();
} catch( UnsupportedLookAndFeelException ex ) {
ex.printStackTrace();
}
} );
}
/**
* Update UI of all application windows.
* Invoke after changing LaF.
*/
public static void updateUI() {
for( Window w : Window.getWindows() )
SwingUtilities.updateComponentTreeUI( w );
}
public static boolean isShowMnemonics() { public static boolean isShowMnemonics() {
return altKeyPressed || !UIManager.getBoolean( "Component.hideMnemonics" ); return altKeyPressed || !UIManager.getBoolean( "Component.hideMnemonics" );
} }

View File

@@ -24,6 +24,10 @@ package com.formdev.flatlaf;
public class FlatLightLaf public class FlatLightLaf
extends FlatLaf extends FlatLaf
{ {
public static boolean install( ) {
return install( new FlatLightLaf() );
}
@Override @Override
public String getName() { public String getName() {
return "Flat Light"; return "Flat Light";

View File

@@ -0,0 +1,248 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import javax.swing.text.StyleContext;
import com.formdev.flatlaf.util.SystemInfo;
/**
* @author Karl Tauber
*/
class LinuxFontPolicy
{
static Font getFont() {
return SystemInfo.IS_KDE ? getKDEFont() : getGnomeFont();
}
/**
* Gets the default font for Gnome.
*/
private static Font getGnomeFont() {
// see class com.sun.java.swing.plaf.gtk.PangoFonts background information
Object fontName = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Gtk/FontName" );
if( !(fontName instanceof String) )
fontName = "sans 10";
String family = "";
int style = Font.PLAIN;
int size = 10;
StringTokenizer st = new StringTokenizer( (String) fontName );
while( st.hasMoreTokens() ) {
String word = st.nextToken();
if( word.equalsIgnoreCase( "italic" ) )
style |= Font.ITALIC;
else if( word.equalsIgnoreCase( "bold" ) )
style |= Font.BOLD;
else if( Character.isDigit( word.charAt( 0 ) ) ) {
try {
size = Integer.parseInt( word );
} catch( NumberFormatException ex ) {
// ignore
}
} else
family = family.isEmpty() ? word : (family + ' ' + word);
}
// scale font size
double dsize = size * getGnomeFontScale();
size = (int) (dsize + 0.5);
if( size < 1 )
size = 1;
// handle logical font names
String logicalFamily = mapFcName( family.toLowerCase() );
if( logicalFamily != null )
family = logicalFamily;
return createFont( family, style, size, dsize );
}
private static Font createFont( String family, int style, int size, double dsize ) {
// using StyleContext.getFont() here because it uses
// sun.font.FontUtilities.getCompositeFontUIResource()
Font font = new StyleContext().getFont( family, style, size );
// set font size in floating points
font = font.deriveFont( style, (float) dsize );
return font;
}
private static double getGnomeFontScale() {
// see class com.sun.java.swing.plaf.gtk.PangoFonts background information
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
if( value instanceof Integer ) {
int dpi = ((Integer)value).intValue() / 1024;
if( dpi == -1 )
dpi = 96;
if( dpi < 50 )
dpi = 50;
return dpi / 72.0;
} else {
return GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice().getDefaultConfiguration()
.getNormalizingTransform().getScaleY();
}
}
/**
* map GTK/fontconfig names to equivalent JDK logical font name
*/
private static String mapFcName( String name ) {
switch( name ) {
case "sans": return "sansserif";
case "sans-serif": return "sansserif";
case "serif": return "serif";
case "monospace": return "monospaced";
}
return null;
}
/**
* Gets the default font for KDE for KDE configuration files.
*
* The Swing fonts are not updated when the user changes system font size
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
* This is the same behavior as in native KDE applications.
*
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
* KDE also does not use it to calculate font size. Only forceFontDPI is used by KDE.
* If user changes "display scale factor" (System Settings > Display and Monitors >
* Displays > Scale Display), the forceFontDPI is also changed to reflect the scale factor.
*/
private static Font getKDEFont() {
List<String> kdeglobals = readConfig( "kdeglobals" );
List<String> kcmfonts = readConfig( "kcmfonts" );
String generalFont = getConfigEntry( kdeglobals, "General", "font" );
String forceFontDPI = getConfigEntry( kcmfonts, "General", "forceFontDPI" );
String family = "sansserif";
int style = Font.PLAIN;
int size = 10;
if( generalFont != null ) {
List<String> strs = FlatLaf.split( generalFont, ',' );
try {
family = strs.get( 0 );
size = Integer.parseInt( strs.get( 1 ) );
if( "75".equals( strs.get( 4 ) ) )
style |= Font.BOLD;
if( "1".equals( strs.get( 5 ) ) )
style |= Font.ITALIC;
} catch( RuntimeException ex ) {
ex.printStackTrace();
}
}
// font dpi
int dpi = 96;
if( forceFontDPI != null ) {
try {
dpi = Integer.parseInt( forceFontDPI );
if( dpi <= 0 )
dpi = 96;
if( dpi < 50 )
dpi = 50;
} catch( NumberFormatException ex ) {
ex.printStackTrace();
}
}
// scale font size
double fontScale = dpi / 72.0;
double dsize = size * fontScale;
size = (int) (dsize + 0.5);
if( size < 1 )
size = 1;
return createFont( family, style, size, dsize );
}
private static List<String> readConfig( String filename ) {
File userHome = new File( System.getProperty( "user.home" ) );
// search for config file
String[] configDirs = {
".config", // KDE 5
".kde4/share/config", // KDE 4
".kde/share/config"// KDE 3
};
File file = null;
for( String configDir : configDirs ) {
file = new File( userHome, configDir + "/" + filename );
if( file.isFile() )
break;
}
if( !file.isFile() )
return Collections.emptyList();
// read config file
ArrayList<String> lines = new ArrayList<>( 200 );
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
String line = null;
while( (line = reader.readLine()) != null )
lines.add( line );
} catch( IOException ex ) {
ex.printStackTrace();
}
return lines;
}
private static String getConfigEntry( List<String> config, String group, String key ) {
int groupLength = group.length();
int keyLength = key.length();
boolean inGroup = false;
for( String line : config ) {
if( !inGroup ) {
if( line.length() >= groupLength + 2 &&
line.charAt( 0 ) == '[' &&
line.charAt( groupLength + 1 ) == ']' &&
line.indexOf( group ) == 1 )
{
inGroup = true;
}
} else {
if( line.startsWith( "[" ) )
return null;
if( line.length() >= keyLength + 2 &&
line.charAt( keyLength ) == '=' &&
line.startsWith( key ) )
{
return line.substring( keyLength + 1 );
}
}
}
return null;
}
}

View File

@@ -157,7 +157,7 @@ public class FlatArrowButton
g.translate( -x, -y ); g.translate( -x, -y );
} }
public static Shape createArrowShape( int direction, boolean chevron, int w, int h ) { public static Shape createArrowShape( int direction, boolean chevron, float w, float h ) {
switch( direction ) { switch( direction ) {
case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h ); case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h );
case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 ); case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 );

View File

@@ -72,9 +72,10 @@ public class FlatBorder
try { try {
FlatUIUtils.setRenderingHints( g2 ); FlatUIUtils.setRenderingHints( g2 );
float focusWidth = getFocusWidth(); boolean isCellEditor = FlatUIUtils.isTableCellEditor( c );
float focusWidth = isCellEditor ? 0 : getFocusWidth();
float borderWidth = getBorderWidth( c ); float borderWidth = getBorderWidth( c );
float arc = getArc(); float arc = isCellEditor ? 0 : getArc();
if( isFocused( c ) ) { if( isFocused( c ) ) {
g2.setColor( getFocusColor( c ) ); g2.setColor( getFocusColor( c ) );
@@ -134,7 +135,8 @@ public class FlatBorder
@Override @Override
public Insets getBorderInsets( Component c, Insets insets ) { public Insets getBorderInsets( Component c, Insets insets ) {
float ow = getFocusWidth() + getLineWidth(); boolean isCellEditor = FlatUIUtils.isTableCellEditor( c );
float ow = (isCellEditor ? 0 : getFocusWidth()) + getLineWidth();
insets = super.getBorderInsets( c, insets ); insets = super.getBorderInsets( c, insets );
insets.top = Math.round( scale( (float) insets.top ) + ow ); insets.top = Math.round( scale( (float) insets.top ) + ow );

View File

@@ -218,7 +218,7 @@ public class FlatButtonUI
paintText( g, b, textRect, text, b.isEnabled() ? getForeground( b ) : disabledText ); paintText( g, b, textRect, text, b.isEnabled() ? getForeground( b ) : disabledText );
} }
static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) { public static void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text, Color foreground ) {
FontMetrics fm = b.getFontMetrics( b.getFont() ); FontMetrics fm = b.getFontMetrics( b.getFont() );
int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1; int mnemonicIndex = FlatLaf.isShowMnemonics() ? b.getDisplayedMnemonicIndex() : -1;

View File

@@ -368,7 +368,6 @@ public class FlatComboBoxUI
@SuppressWarnings( { "rawtypes", "unchecked" } ) @SuppressWarnings( { "rawtypes", "unchecked" } )
private class FlatComboPopup private class FlatComboPopup
extends BasicComboPopup extends BasicComboPopup
implements ListCellRenderer
{ {
private CellPaddingBorder paddingBorder; private CellPaddingBorder paddingBorder;
@@ -405,7 +404,7 @@ public class FlatComboBoxUI
protected void configureList() { protected void configureList() {
super.configureList(); super.configureList();
list.setCellRenderer( this ); list.setCellRenderer( new PopupListCellRenderer() );
} }
@Override @Override
@@ -416,11 +415,16 @@ public class FlatComboBoxUI
super.propertyChange( e ); super.propertyChange( e );
if( e.getPropertyName() == "renderer" ) if( e.getPropertyName() == "renderer" )
list.setCellRenderer( FlatComboPopup.this ); list.setCellRenderer( new PopupListCellRenderer() );
} }
}; };
} }
//---- class PopupListCellRenderer -----
private class PopupListCellRenderer
implements ListCellRenderer
{
@Override @Override
public Component getListCellRendererComponent( JList list, Object value, public Component getListCellRendererComponent( JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus ) int index, boolean isSelected, boolean cellHasFocus )
@@ -439,6 +443,7 @@ public class FlatComboBoxUI
return c; return c;
} }
} }
}
//---- class CellPaddingBorder -------------------------------------------- //---- class CellPaddingBorder --------------------------------------------

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension; import java.awt.Dimension;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicEditorPaneUI; import javax.swing.plaf.basic.BasicEditorPaneUI;
@@ -37,6 +38,8 @@ public class FlatEditorPaneUI
{ {
protected int minimumWidth; protected int minimumWidth;
private Object oldHonorDisplayProperties;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatEditorPaneUI(); return new FlatEditorPaneUI();
} }
@@ -46,6 +49,17 @@ public class FlatEditorPaneUI
super.installDefaults(); super.installDefaults();
minimumWidth = UIManager.getInt( "Component.minimumWidth" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
} }
@Override @Override

View File

@@ -23,6 +23,7 @@ import java.awt.GridBagConstraints;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.plaf.basic.BasicOptionPaneUI; import javax.swing.plaf.basic.BasicOptionPaneUI;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -122,6 +123,10 @@ public class FlatOptionPaneUI
if( messagePadding > 0 ) if( messagePadding > 0 )
cons.insets.bottom = UIScale.scale( messagePadding ); cons.insets.bottom = UIScale.scale( messagePadding );
// disable line wrapping for HTML
if( msg instanceof String && BasicHTML.isHTMLString( (String) msg ) )
maxll = Integer.MAX_VALUE;
super.addMessageComponents( container, cons, msg, maxll, internallyCreated ); super.addMessageComponents( container, cons, msg, maxll, internallyCreated );
} }

View File

@@ -116,15 +116,16 @@ public class FlatPasswordFieldUI
@Override @Override
public Dimension getPreferredSize( JComponent c ) { public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( super.getPreferredSize( c ) ); return applyMinimumWidth( super.getPreferredSize( c ), c );
} }
@Override @Override
public Dimension getMinimumSize( JComponent c ) { public Dimension getMinimumSize( JComponent c ) {
return applyMinimumWidth( super.getMinimumSize( c ) ); return applyMinimumWidth( super.getMinimumSize( c ), c );
} }
private Dimension applyMinimumWidth( Dimension size ) { private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) ); size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size; return size;
} }

View File

@@ -128,6 +128,7 @@ public class FlatTextFieldUI
(parent != null && parent.getParent() instanceof JSpinner) ) (parent != null && parent.getParent() instanceof JSpinner) )
return size; return size;
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) ); size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size; return size;
} }

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension; import java.awt.Dimension;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextPaneUI; import javax.swing.plaf.basic.BasicTextPaneUI;
@@ -37,6 +38,8 @@ public class FlatTextPaneUI
{ {
protected int minimumWidth; protected int minimumWidth;
private Object oldHonorDisplayProperties;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatTextPaneUI(); return new FlatTextPaneUI();
} }
@@ -46,6 +49,17 @@ public class FlatTextPaneUI
super.installDefaults(); super.installDefaults();
minimumWidth = UIManager.getInt( "Component.minimumWidth" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
} }
@Override @Override

View File

@@ -19,6 +19,8 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Component; import java.awt.Component;
import java.awt.Insets; import java.awt.Insets;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.UIManager; import javax.swing.UIManager;
@@ -53,6 +55,29 @@ public class FlatToolBarUI
rolloverBorder = null; rolloverBorder = null;
} }
@Override
protected ContainerListener createToolBarContListener() {
return new ToolBarContListener() {
@Override
public void componentAdded( ContainerEvent e ) {
super.componentAdded( e );
Component c = e.getChild();
if( c instanceof AbstractButton )
c.setFocusable( false );
}
@Override
public void componentRemoved( ContainerEvent e ) {
super.componentRemoved( e );
Component c = e.getChild();
if( c instanceof AbstractButton )
c.setFocusable( true );
}
};
}
@Override @Override
protected Border createRolloverBorder() { protected Border createRolloverBorder() {
return getRolloverBorder(); return getRolloverBorder();

View File

@@ -17,7 +17,9 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.Color; import java.awt.Color;
import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Insets; import java.awt.Insets;
@@ -61,6 +63,12 @@ public class FlatUIUtils
r.height - insets.top - insets.bottom ); r.height - insets.top - insets.bottom );
} }
public static Dimension addInsets( Dimension dim, Insets insets ) {
return new Dimension(
dim.width + insets.left + insets.right,
dim.height + insets.top + insets.bottom );
}
public static Color getUIColor( String key, int defaultColorRGB ) { public static Color getUIColor( String key, int defaultColorRGB ) {
Color color = UIManager.getColor( key ); Color color = UIManager.getColor( key );
return (color != null) ? color : new Color( defaultColorRGB ); return (color != null) ? color : new Color( defaultColorRGB );
@@ -80,6 +88,10 @@ public class FlatUIUtils
return (c instanceof ColorUIResource) ? new Color( c.getRGB(), true ) : c; return (c instanceof ColorUIResource) ? new Color( c.getRGB(), true ) : c;
} }
public static boolean isTableCellEditor( Component c ) {
return c instanceof JComponent && Boolean.TRUE.equals( ((JComponent)c).getClientProperty( "JComboBox.isTableCellEditor" ) );
}
/** /**
* Sets rendering hints used for painting. * Sets rendering hints used for painting.
*/ */
@@ -160,21 +172,52 @@ public class FlatUIUtils
} }
private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) { private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) {
if( arc <= 0 ) return createRoundRectanglePath( x, y, width, height, arc, arc, arc, arc );
}
/**
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
*/
public static Path2D createRoundRectangle( float x, float y, float width, float height,
float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createRoundRectanglePath( x, y, width, height, arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight ), false );
path.append( createRoundRectanglePath( x + lineWidth, y + lineWidth, width - (lineWidth * 2), height - (lineWidth * 2),
arcTopLeft - lineWidth, arcTopRight - lineWidth, arcBottomLeft - lineWidth, arcBottomRight - lineWidth ), false );
return path;
}
/**
* Creates a filled rounded rectangle shape and allows specifying the radius or each corner.
*/
public static Shape createRoundRectanglePath( float x, float y, float width, float height,
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
if( arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0 && arcBottomRight <= 0 )
return new Rectangle2D.Float( x, y, width, height ); 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;
float x2 = x + width; float x2 = x + width;
float y2 = y + height; float y2 = y + height;
Path2D rect = new Path2D.Float(); Path2D rect = new Path2D.Float();
rect.moveTo( x2 - arc, y ); rect.moveTo( x2 - arcTopRight, y );
rect.quadTo( x2, y, x2, y + arc ); rect.quadTo( x2, y, x2, y + arcTopRight );
rect.lineTo( x2, y2 - arc ); rect.lineTo( x2, y2 - arcBottomRight );
rect.quadTo( x2, y2, x2 - arc, y2 ); rect.quadTo( x2, y2, x2 - arcBottomRight, y2 );
rect.lineTo( x + arc, y2 ); rect.lineTo( x + arcBottomLeft, y2 );
rect.quadTo( x, y2, x, y2 - arc ); rect.quadTo( x, y2, x, y2 - arcBottomLeft );
rect.lineTo( x, y + arc ); rect.lineTo( x, y + arcTopLeft );
rect.quadTo( x, y, x + arc, y ); rect.quadTo( x, y, x + arcTopLeft, y );
rect.closePath(); rect.closePath();
return rect; return rect;

View File

@@ -40,6 +40,9 @@ public class SystemInfo
// Java VMs // Java VMs
public static final boolean IS_JETBRAINS_JVM; public static final boolean IS_JETBRAINS_JVM;
// UI toolkits
public static final boolean IS_KDE;
static { static {
// platforms // platforms
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH ); String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
@@ -58,6 +61,9 @@ public class SystemInfo
// Java VMs // Java VMs
IS_JETBRAINS_JVM = System.getProperty( "java.vm.vendor", "Unknown" ) IS_JETBRAINS_JVM = System.getProperty( "java.vm.vendor", "Unknown" )
.toLowerCase( Locale.ENGLISH ).contains( "jetbrains" ); .toLowerCase( Locale.ENGLISH ).contains( "jetbrains" );
// UI toolkits
IS_KDE = (IS_LINUX && System.getenv( "KDE_FULL_SESSION" ) != null);
} }
private static long scanVersion( String version ) { private static long scanVersion( String version ) {

View File

@@ -48,8 +48,7 @@ import javax.swing.plaf.UIResource;
* *
* 2) user scaling mode * 2) user scaling mode
* *
* This mode is for Java 8 compatibility and can be removed when changing minimum * This mode is mainly for Java 8 compatibility, but is also used on Linux.
* required Java version to 9.
* The user scale factor is computed based on the used font. * The user scale factor is computed based on the used font.
* The JRE does not scale anything. * The JRE does not scale anything.
* So we have to invoke {@link #scale(float)} where necessary. * So we have to invoke {@link #scale(float)} where necessary.
@@ -66,7 +65,7 @@ public class UIScale
private static Boolean jreHiDPI; private static Boolean jreHiDPI;
public static boolean isJreHiDPIEnabled() { public static boolean isSystemScalingEnabled() {
if( jreHiDPI != null ) if( jreHiDPI != null )
return jreHiDPI; return jreHiDPI;
@@ -94,11 +93,11 @@ public class UIScale
} }
public static double getSystemScaleFactor( Graphics2D g ) { public static double getSystemScaleFactor( Graphics2D g ) {
return isJreHiDPIEnabled() ? g.getDeviceConfiguration().getDefaultTransform().getScaleX() : 1; return isSystemScalingEnabled() ? g.getDeviceConfiguration().getDefaultTransform().getScaleX() : 1;
} }
public static double getSystemScaleFactor( GraphicsConfiguration gc ) { public static double getSystemScaleFactor( GraphicsConfiguration gc ) {
return isJreHiDPIEnabled() ? gc.getDefaultTransform().getScaleX() : 1; return isSystemScalingEnabled() ? gc.getDefaultTransform().getScaleX() : 1;
} }
//---- user scaling (Java 8) ---------------------------------------------- //---- user scaling (Java 8) ----------------------------------------------
@@ -111,7 +110,7 @@ public class UIScale
return; return;
initialized = true; initialized = true;
if( isEnabled() ) { if( isUserScalingEnabled() ) {
// listener to update scale factor if LaF changed or if Label.font changed // listener to update scale factor if LaF changed or if Label.font changed
// (e.g. option "Override default fonts" in IntelliJ IDEA) // (e.g. option "Override default fonts" in IntelliJ IDEA)
PropertyChangeListener listener = new PropertyChangeListener() { PropertyChangeListener listener = new PropertyChangeListener() {
@@ -135,7 +134,7 @@ public class UIScale
} }
private static void updateScaleFactor() { private static void updateScaleFactor() {
if( !isEnabled() ) if( !isUserScalingEnabled() )
return; return;
// use font size to calculate scale factor (instead of DPI) // use font size to calculate scale factor (instead of DPI)
@@ -158,15 +157,15 @@ public class UIScale
if( "Tahoma".equals( font.getFamily() ) ) if( "Tahoma".equals( font.getFamily() ) )
fontSizeDivider = 11f; fontSizeDivider = 11f;
} else if( SystemInfo.IS_LINUX ) { } else if( SystemInfo.IS_LINUX ) {
// default font size for Unity and Gnome is 15 // default font size for Unity and Gnome is 15 and for KDE it is 13
fontSizeDivider = 15f; fontSizeDivider = SystemInfo.IS_KDE ? 13f : 15f;
} }
return font.getSize() / fontSizeDivider; return font.getSize() / fontSizeDivider;
} }
private static boolean isEnabled() { private static boolean isUserScalingEnabled() {
if( isJreHiDPIEnabled() ) if( isSystemScalingEnabled() && !SystemInfo.IS_LINUX )
return false; // disable user scaling if JRE scales return false; // disable user scaling if JRE scales
// same as in IntelliJ IDEA // same as in IntelliJ IDEA
@@ -179,7 +178,7 @@ public class UIScale
* or "sun.java2d.uiScale" to the given font. * or "sun.java2d.uiScale" to the given font.
*/ */
public static FontUIResource applyCustomScaleFactor( FontUIResource font ) { public static FontUIResource applyCustomScaleFactor( FontUIResource font ) {
if( UIScale.isJreHiDPIEnabled() ) if( UIScale.isSystemScalingEnabled() )
return font; return font;
String uiScale = System.getProperty( "flatlaf.uiScale" ); String uiScale = System.getProperty( "flatlaf.uiScale" );

View File

@@ -227,7 +227,8 @@ ToggleButton.toolbar.selectedBackground=5c6164
#---- ToolTip ---- #---- ToolTip ----
ToolTip.background=4b4d4d ToolTip.border=4,6,4,6
ToolTip.background=1e2123
#---- Tree ---- #---- Tree ----

View File

@@ -212,7 +212,7 @@ OptionPane.maxCharactersPerLine=80
OptionPane.iconMessageGap=16 OptionPane.iconMessageGap=16
OptionPane.messagePadding=3 OptionPane.messagePadding=3
OptionPane.buttonPadding=8 OptionPane.buttonPadding=8
OptionPane.buttonMinimumWidth=72 OptionPane.buttonMinimumWidth={scaledNumber}72
OptionPane.sameSizeButtons=true OptionPane.sameSizeButtons=true
OptionPane.setButtonMargin=false OptionPane.setButtonMargin=false
OptionPane.buttonOrientation=4 OptionPane.buttonOrientation=4
@@ -307,12 +307,12 @@ Spinner.editorBorderPainted=false
#---- SplitPane ---- #---- SplitPane ----
SplitPane.dividerSize=5 SplitPane.dividerSize={integer}5
SplitPane.continuousLayout=true SplitPane.continuousLayout=true
SplitPane.border=null SplitPane.border=null
SplitPane.centerOneTouchButtons=true SplitPane.centerOneTouchButtons=true
SplitPane.oneTouchButtonSize=6 SplitPane.oneTouchButtonSize={scaledNumber}6
SplitPane.oneTouchButtonOffset=2 SplitPane.oneTouchButtonOffset={scaledNumber}2
SplitPaneDivider.border=null SplitPaneDivider.border=null
SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor
@@ -409,7 +409,9 @@ ToolBar.separatorColor=@@Separator.foreground
#---- ToolTip ---- #---- ToolTip ----
ToolTip.border=2,6,2,6,@@Component.borderColor ToolTip.borderInactive=null
ToolTip.backgroundInactive=@@ToolTip.background
ToolTip.foregroundInactive=@disabledText
#---- Tree ---- #---- Tree ----

View File

@@ -234,7 +234,8 @@ ToggleButton.toolbar.selectedBackground=cfcfcf
#---- ToolTip ---- #---- ToolTip ----
ToolTip.background=f7f7f7 ToolTip.border=4,6,4,6,@@Component.borderColor
ToolTip.background=fafafa
#---- Tree ---- #---- Tree ----

View File

@@ -143,7 +143,14 @@ public class FlatComponentsTest
JToggleButton toggleButton7 = new JToggleButton(); JToggleButton toggleButton7 = new JToggleButton();
JLabel scrollBarLabel = new JLabel(); JLabel scrollBarLabel = new JLabel();
JScrollBar scrollBar1 = new JScrollBar(); JScrollBar scrollBar1 = new JScrollBar();
JLabel label4 = new JLabel();
JScrollBar scrollBar4 = new JScrollBar(); JScrollBar scrollBar4 = new JScrollBar();
JPanel panel3 = new JPanel();
JLabel label3 = new JLabel();
JScrollPane scrollPane15 = new JScrollPane();
JEditorPane editorPane6 = new JEditorPane();
JScrollPane scrollPane16 = new JScrollPane();
JTextPane textPane6 = new JTextPane();
JLabel separatorLabel = new JLabel(); JLabel separatorLabel = new JLabel();
JSeparator separator1 = new JSeparator(); JSeparator separator1 = new JSeparator();
JPanel panel2 = new JPanel(); JPanel panel2 = new JPanel();
@@ -223,12 +230,14 @@ public class FlatComponentsTest
//---- button1 ---- //---- button1 ----
button1.setText("enabled"); button1.setText("enabled");
button1.setDisplayedMnemonicIndex(0); button1.setDisplayedMnemonicIndex(0);
button1.setToolTipText("This button is enabled.");
add(button1, "cell 1 1"); add(button1, "cell 1 1");
//---- button2 ---- //---- button2 ----
button2.setText("disabled"); button2.setText("disabled");
button2.setDisplayedMnemonicIndex(0); button2.setDisplayedMnemonicIndex(0);
button2.setEnabled(false); button2.setEnabled(false);
button2.setToolTipText("This button is disabled.");
add(button2, "cell 2 1"); add(button2, "cell 2 1");
//---- button5 ---- //---- button5 ----
@@ -719,11 +728,52 @@ public class FlatComponentsTest
scrollBar1.setOrientation(Adjustable.HORIZONTAL); scrollBar1.setOrientation(Adjustable.HORIZONTAL);
add(scrollBar1, "cell 1 14,growx"); add(scrollBar1, "cell 1 14,growx");
//---- label4 ----
label4.setText("HTML:");
add(label4, "cell 5 14");
//---- scrollBar4 ---- //---- scrollBar4 ----
scrollBar4.setOrientation(Adjustable.HORIZONTAL); scrollBar4.setOrientation(Adjustable.HORIZONTAL);
scrollBar4.setEnabled(false); scrollBar4.setEnabled(false);
add(scrollBar4, "cell 1 15,growx"); add(scrollBar4, "cell 1 15,growx");
//======== panel3 ========
{
panel3.setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
// columns
"[]",
// rows
"[]" +
"[]" +
"[]"));
//---- label3 ----
label3.setText("<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>");
panel3.add(label3, "cell 0 0");
//======== scrollPane15 ========
{
//---- editorPane6 ----
editorPane6.setContentType("text/html");
editorPane6.setText("JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u>");
scrollPane15.setViewportView(editorPane6);
}
panel3.add(scrollPane15, "cell 0 1,grow");
//======== scrollPane16 ========
{
//---- textPane6 ----
textPane6.setContentType("text/html");
textPane6.setText("JTextPane HTML<br>Sample <b>content</b><br> <u>text</u>");
scrollPane16.setViewportView(textPane6);
}
panel3.add(scrollPane16, "cell 0 2,grow");
}
add(panel3, "cell 5 15 1 7,aligny top,grow 100 0");
//---- separatorLabel ---- //---- separatorLabel ----
separatorLabel.setText("JSeparator:"); separatorLabel.setText("JSeparator:");
add(separatorLabel, "cell 0 16"); add(separatorLabel, "cell 0 16");

View File

@@ -43,6 +43,7 @@ new FormModel {
name: "button1" name: "button1"
"text": "enabled" "text": "enabled"
"displayedMnemonicIndex": 0 "displayedMnemonicIndex": 0
"toolTipText": "This button is enabled."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1" "value": "cell 1 1"
} ) } )
@@ -51,6 +52,7 @@ new FormModel {
"text": "disabled" "text": "disabled"
"displayedMnemonicIndex": 0 "displayedMnemonicIndex": 0
"enabled": false "enabled": false
"toolTipText": "This button is disabled."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1" "value": "cell 2 1"
} ) } )
@@ -678,6 +680,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 14,growx" "value": "cell 1 14,growx"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "HTML:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 14"
} )
add( new FormComponent( "javax.swing.JScrollBar" ) { add( new FormComponent( "javax.swing.JScrollBar" ) {
name: "scrollBar4" name: "scrollBar4"
"orientation": 0 "orientation": 0
@@ -685,6 +693,41 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15,growx" "value": "cell 1 15,growx"
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[][][]"
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
} ) {
name: "panel3"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane15"
add( new FormComponent( "javax.swing.JEditorPane" ) {
name: "editorPane6"
"contentType": "text/html"
"text": "JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u>"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,grow"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane16"
add( new FormComponent( "javax.swing.JTextPane" ) {
name: "textPane6"
"contentType": "text/html"
"text": "JTextPane HTML<br>Sample <b>content</b><br> <u>text</u>"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2,grow"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 15 1 7,aligny top,grow 100 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "separatorLabel" name: "separatorLabel"
"text": "JSeparator:" "text": "JSeparator:"
@@ -837,7 +880,7 @@ new FormModel {
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 715 ) "size": new java.awt.Dimension( 790, 750 )
} ) } )
} }
} }

View File

@@ -23,6 +23,7 @@ import java.awt.Dimension;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets; import java.awt.Insets;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
@@ -41,6 +42,7 @@ import javax.swing.border.LineBorder;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent; import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.ui.FlatToolTipUI; import com.formdev.flatlaf.ui.FlatToolTipUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
/** /**
@@ -103,7 +105,7 @@ public class FlatInspector
private void inspect( int x, int y ) { private void inspect( int x, int y ) {
Container contentPane = rootPane.getContentPane(); Container contentPane = rootPane.getContentPane();
Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y ); Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y );
if( c == contentPane || c.getParent() == contentPane ) if( c == contentPane || (c != null && c.getParent() == contentPane) )
c = null; c = null;
if( c == lastComponent ) if( c == lastComponent )
@@ -137,6 +139,12 @@ public class FlatInspector
g.setColor( getBackground() ); g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() ); g.fillRect( 0, 0, getWidth(), getHeight() );
} }
@Override
protected void paintBorder( Graphics g ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paintBorder( g );
}
}; };
c.setBackground( new Color( 255, 0, 0, 32 ) ); c.setBackground( new Color( 255, 0, 0, 32 ) );
c.setBorder( new LineBorder( Color.red ) ); c.setBorder( new LineBorder( Color.red ) );
@@ -228,6 +236,9 @@ public class FlatInspector
} }
} }
text += "Enabled: " + c.isEnabled() + '\n';
text += "Opaque: " + c.isOpaque() + '\n';
text += "Focusable: " + c.isFocusable() + '\n';
text += "Parent: " + c.getParent().getClass().getName(); text += "Parent: " + c.getParent().getClass().getName();
return text; return text;

View File

@@ -201,7 +201,7 @@ public class FlatOptionPaneTest
//---- warningOptionPane ---- //---- warningOptionPane ----
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE); warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION); warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
warningOptionPane.setMessage("Beware of the dog!"); 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); panel5.add(warningOptionPane, BorderLayout.CENTER);
} }
add(panel5, "cell 1 4"); add(panel5, "cell 1 4");

View File

@@ -140,7 +140,7 @@ new FormModel {
name: "warningOptionPane" name: "warningOptionPane"
"messageType": 2 "messageType": 2
"optionType": 2 "optionType": 2
"message": "Beware of the dog!" "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 ) { }, new FormLayoutConstraints( class java.lang.String ) {
"value": "Center" "value": "Center"
} ) } )

View File

@@ -22,6 +22,7 @@ import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.util.function.BiConsumer;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
@@ -68,11 +69,7 @@ public class FlatTestFrame
ex.printStackTrace(); ex.printStackTrace();
// fallback // fallback
try { FlatLightLaf.install();
UIManager.setLookAndFeel( new FlatLightLaf() );
} catch( Exception ex2 ) {
ex2.printStackTrace();
}
} }
// create frame // create frame
@@ -101,7 +98,8 @@ public class FlatTestFrame
continue; continue;
if( (SystemInfo.IS_WINDOWS && className.equals( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" )) || if( (SystemInfo.IS_WINDOWS && className.equals( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" )) ||
(SystemInfo.IS_MAC && className.equals( "com.apple.laf.AquaLookAndFeel") ) ) (SystemInfo.IS_MAC && className.equals( "com.apple.laf.AquaLookAndFeel") ) ||
(SystemInfo.IS_LINUX && className.equals( "com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ) )
name += " (F9)"; name += " (F9)";
else if( className.equals( MetalLookAndFeel.class.getName() ) ) else if( className.equals( MetalLookAndFeel.class.getName() ) )
name += " (F10)"; name += " (F10)";
@@ -139,6 +137,8 @@ public class FlatTestFrame
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" ); registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
else if( SystemInfo.IS_MAC ) else if( SystemInfo.IS_MAC )
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.apple.laf.AquaLookAndFeel" ); 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_F10, MetalLookAndFeel.class.getName() );
registerSwitchToLookAndFeel( KeyEvent.VK_F11, NimbusLookAndFeel.class.getName() ); registerSwitchToLookAndFeel( KeyEvent.VK_F11, NimbusLookAndFeel.class.getName() );
@@ -168,6 +168,18 @@ public class FlatTestFrame
updateTitle(); updateTitle();
} }
} ); } );
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
EventQueue.invokeLater( () -> {
// update title because user scale factor may change
updateTitle();
// enable/disable scale factor combobox
updateScaleFactorComboBox();
} );
}
} );
} }
private void updateTitle() { private void updateTitle() {
@@ -192,7 +204,7 @@ public class FlatTestFrame
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
} }
protected void showFrame( JComponent content ) { public void showFrame( JComponent content ) {
this.content = content; this.content = content;
contentPanel.getContentPane().add( content ); contentPanel.getContentPane().add( content );
@@ -234,14 +246,8 @@ public class FlatTestFrame
// change look and feel // change look and feel
UIManager.setLookAndFeel( lafClassName ); UIManager.setLookAndFeel( lafClassName );
// update title because user scale factor may change
updateTitle();
// enable/disable scale factor combobox
updateScaleFactorComboBox();
// update all components // update all components
SwingUtilities.updateComponentTreeUI( this ); FlatLaf.updateUI();
// increase size of frame if necessary // increase size of frame if necessary
if( pack ) if( pack )
@@ -283,7 +289,15 @@ public class FlatTestFrame
boolean explicit = explicitColorsCheckBox.isSelected(); boolean explicit = explicitColorsCheckBox.isSelected();
ColorUIResource restoreColor = new ColorUIResource( Color.white ); ColorUIResource restoreColor = new ColorUIResource( Color.white );
explicitColors( content, explicit, restoreColor ); updateComponentsRecur( content, (c, type) -> {
if( type == "view" || type == "tab" ) {
c.setForeground( explicit ? Color.magenta : restoreColor );
c.setBackground( explicit ? Color.orange : restoreColor );
} else {
c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.red : restoreColor );
}
} );
// because colors may depend on state (e.g. disabled JTextField) // because colors may depend on state (e.g. disabled JTextField)
// it is best to update all UI delegates to get correct result // it is best to update all UI delegates to get correct result
@@ -292,40 +306,6 @@ public class FlatTestFrame
} ); } );
} }
private void explicitColors( Container container, boolean explicit, ColorUIResource restoreColor ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
explicitColors( (JPanel) c, explicit, restoreColor );
continue;
}
c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.red : restoreColor );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null ) {
view.setForeground( explicit ? Color.magenta : restoreColor );
view.setBackground( explicit ? Color.orange : restoreColor );
}
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null ) {
tab.setForeground( explicit ? Color.magenta : restoreColor );
tab.setBackground( explicit ? Color.orange : restoreColor );
}
}
}
if( c instanceof JToolBar )
explicitColors( (JToolBar) c, explicit, restoreColor );
}
}
private void rightToLeftChanged() { private void rightToLeftChanged() {
contentPanel.applyComponentOrientation( rightToLeftCheckBox.isSelected() contentPanel.applyComponentOrientation( rightToLeftCheckBox.isSelected()
? ComponentOrientation.RIGHT_TO_LEFT ? ComponentOrientation.RIGHT_TO_LEFT
@@ -335,35 +315,10 @@ public class FlatTestFrame
} }
private void enabledChanged() { private void enabledChanged() {
enabledDisable( content, enabledCheckBox.isSelected() ); boolean enabled = enabledCheckBox.isSelected();
} updateComponentsRecur( content, (c, type) -> {
private void enabledDisable( Container container, boolean enabled ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
enabledDisable( (JPanel) c, enabled );
continue;
}
c.setEnabled( enabled ); c.setEnabled( enabled );
} );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null )
view.setEnabled( enabled );
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null )
tab.setEnabled( enabled );
}
}
if( c instanceof JToolBar )
enabledDisable( (JToolBar) c, enabled );
}
} }
private void inspectChanged() { private void inspectChanged() {
@@ -394,7 +349,35 @@ public class FlatTestFrame
} }
private void updateScaleFactorComboBox() { private void updateScaleFactorComboBox() {
scaleFactorComboBox.setEnabled( !UIScale.isJreHiDPIEnabled() && UIManager.getLookAndFeel() instanceof FlatLaf ); scaleFactorComboBox.setEnabled( !UIScale.isSystemScalingEnabled() && UIManager.getLookAndFeel() instanceof FlatLaf );
}
private void updateComponentsRecur( Container container, BiConsumer<Component, String> action ) {
for( Component c : container.getComponents() ) {
if( c instanceof JPanel ) {
updateComponentsRecur( (JPanel) c, action );
continue;
}
action.accept( c, null );
if( c instanceof JScrollPane ) {
Component view = ((JScrollPane)c).getViewport().getView();
if( view != null )
action.accept( view, "view" );
} else if( c instanceof JTabbedPane ) {
JTabbedPane tabPane = (JTabbedPane)c;
int tabCount = tabPane.getTabCount();
for( int i = 0; i < tabCount; i++ ) {
Component tab = tabPane.getComponentAt( i );
if( tab != null )
action.accept( tab, "tab" );
}
}
if( c instanceof JToolBar )
updateComponentsRecur( (JToolBar) c, action );
}
} }
private void initComponents() { private void initComponents() {

View File

@@ -18,10 +18,7 @@ version = rootProject.version
plugins { plugins {
`java-library` `java-library`
} id( "com.jfrog.bintray" ) version "1.8.4"
repositories {
jcenter()
} }
dependencies { dependencies {
@@ -38,6 +35,8 @@ java {
tasks { tasks {
jar { jar {
dependsOn( ":flatlaf-core:jar" )
manifest { manifest {
attributes( "Main-Class" to "com.formdev.flatlaf.demo.FlatLafDemo" ) attributes( "Main-Class" to "com.formdev.flatlaf.demo.FlatLafDemo" )
} }
@@ -50,3 +49,23 @@ tasks {
} ) } )
} }
} }
bintray {
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
setConfigurations( "archives" )
with( pkg ) {
repo = "flatlaf"
name = "flatlaf-demo"
setLicenses( "Apache-2.0" )
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
with( version ) {
name = project.version.toString()
}
publish = true
}
}

View File

@@ -58,7 +58,8 @@ class ControlBar
continue; continue;
if( (SystemInfo.IS_WINDOWS && className.equals( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" )) || if( (SystemInfo.IS_WINDOWS && className.equals( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" )) ||
(SystemInfo.IS_MAC && className.equals( "com.apple.laf.AquaLookAndFeel") ) ) (SystemInfo.IS_MAC && className.equals( "com.apple.laf.AquaLookAndFeel") ) ||
(SystemInfo.IS_LINUX && className.equals( "com.sun.java.swing.plaf.gtk.GTKLookAndFeel") ) )
name += " (F9)"; name += " (F9)";
else if( className.equals( MetalLookAndFeel.class.getName() ) ) else if( className.equals( MetalLookAndFeel.class.getName() ) )
name += " (F10)"; name += " (F10)";
@@ -78,6 +79,15 @@ class ControlBar
lafModel.setSelectedItem( lafModel.getElementAt( sel ) ); lafModel.setSelectedItem( lafModel.getElementAt( sel ) );
lookAndFeelComboBox.setModel( lafModel ); lookAndFeelComboBox.setModel( lafModel );
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
EventQueue.invokeLater( () -> {
// update info label because user scale factor may change
updateInfoLabel();
} );
}
} );
} }
void initialize( JFrame frame, JTabbedPane tabbedPane ) { void initialize( JFrame frame, JTabbedPane tabbedPane ) {
@@ -94,6 +104,8 @@ class ControlBar
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" ); registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
else if( SystemInfo.IS_MAC ) else if( SystemInfo.IS_MAC )
registerSwitchToLookAndFeel( KeyEvent.VK_F9, "com.apple.laf.AquaLookAndFeel" ); 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_F10, MetalLookAndFeel.class.getName() );
registerSwitchToLookAndFeel( KeyEvent.VK_F11, NimbusLookAndFeel.class.getName() ); registerSwitchToLookAndFeel( KeyEvent.VK_F11, NimbusLookAndFeel.class.getName() );
@@ -170,11 +182,8 @@ class ControlBar
// change look and feel // change look and feel
UIManager.setLookAndFeel( newLaf.className ); UIManager.setLookAndFeel( newLaf.className );
// update info label because user scale factor may change
updateInfoLabel();
// update all components // update all components
SwingUtilities.updateComponentTreeUI( frame ); FlatLaf.updateUI();
// increase size of frame if necessary // increase size of frame if necessary
int width = frame.getWidth(); int width = frame.getWidth();

View File

@@ -46,11 +46,7 @@ public class FlatLafDemo
ex.printStackTrace(); ex.printStackTrace();
// fallback // fallback
try { FlatLightLaf.install();
UIManager.setLookAndFeel( new FlatLightLaf() );
} catch( Exception ex2 ) {
ex2.printStackTrace();
}
} }
// create frame // create frame

View File

@@ -201,7 +201,7 @@ class OptionPanePanel
//---- warningOptionPane ---- //---- warningOptionPane ----
warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE); warningOptionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION); warningOptionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
warningOptionPane.setMessage("Beware of the dog!"); 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); panel5.add(warningOptionPane, BorderLayout.CENTER);
} }
panel9.add(panel5, "cell 1 4"); panel9.add(panel5, "cell 1 4");

View File

@@ -143,7 +143,7 @@ new FormModel {
name: "warningOptionPane" name: "warningOptionPane"
"messageType": 2 "messageType": 2
"optionType": 2 "optionType": 2
"message": "Beware of the dog!" "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 ) { }, new FormLayoutConstraints( class java.lang.String ) {
"value": "Center" "value": "Center"
} ) } )

43
flatlaf-swingx/README.md Normal file
View File

@@ -0,0 +1,43 @@
FlatLaf addon for SwingX
========================
This addon for FlatLaf adds support for **some** widely used SwingX components.
Many SwingX components that do not use UI delegates (e.g. `JXButton`, `JXLabel`,
`JXList`, etc) work with FlatLaf without adaptation.
Following SwingX components, which use UI delegates, are supported by this
addon:
- `JXBusyLabel`
- `JXDatePicker`
- `JXHeader`
- `JXHyperlink`
- `JXMonthView`
- `JXTaskPaneContainer`
- `JXTaskPane`
![Flat Light SwingX Demo](../images/FlatLightSwingXTest.png)
![Flat Dark SwingX Demo](../images/FlatDarkSwingXTest.png)
Download
--------
FlatLaf for SwingX binaries are available on **JCenter** and **Maven Central**.
If you use Maven or Gradle, add a dependency with following coordinates to your
build script:
groupId: com.formdev
artifactId: flatlaf-swingx
version: 0.15
Otherwise download `flatlaf-swingx-<version>.jar` here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf-swingx/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf-swingx/_latestVersion)
You also need `flatlaf-<version>.jar`, which you can download here:
[![Download](https://api.bintray.com/packages/jformdesigner/flatlaf/flatlaf/images/download.svg)](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
version = rootProject.version
plugins {
`java-library`
`maven-publish`
id( "com.jfrog.bintray" ) version "1.8.4"
}
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( "org.swinglabs.swingx:swingx-all:1.6.5-1" )
testImplementation( project( ":flatlaf-core", "testArtifacts" ) )
testImplementation( "org.swinglabs.swingx:swingx-beaninfo:1.6.5-1" )
testImplementation( "com.miglayout:miglayout-swing:5.2" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
javadoc {
options {
this as StandardJavadocDocletOptions
tags = listOf( "uiDefault", "clientProperty" )
}
isFailOnError = false
}
register( "sourcesJar", Jar::class ) {
archiveClassifier.set( "sources" )
from( sourceSets.main.get().allJava )
}
register( "javadocJar", Jar::class ) {
archiveClassifier.set( "javadoc" )
from( javadoc )
}
}
publishing {
publications {
create<MavenPublication>( "maven" ) {
artifactId = "flatlaf-swingx"
groupId = "com.formdev"
from( components["java"] )
artifact( tasks["sourcesJar"] )
artifact( tasks["javadocJar"] )
pom {
name.set( "FlatLaf addon for SwingX" )
description.set( "Flat Look and Feel addon for SwingX" )
url.set( "https://github.com/JFormDesigner/FlatLaf" )
licenses {
license {
name.set( "The Apache License, Version 2.0" )
url.set( "http://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 = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
setPublications( "maven" )
with( pkg ) {
repo = "flatlaf"
name = "flatlaf-swingx"
setLicenses( "Apache-2.0" )
vcsUrl = "https://github.com/JFormDesigner/FlatLaf"
with( version ) {
name = project.version.toString()
}
publish = true
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
import javax.swing.UIManager;
import org.jdesktop.swingx.plaf.basic.BasicLookAndFeelAddons;
import com.formdev.flatlaf.FlatLaf;
/**
* SwingX LaF addon.
*
* This class is required because without this class, the system addon would be used,
* which may result in wrong UI defaults. (e.g. background of TaskPaneContainer)
*
* @author Karl Tauber
*/
public class FlatLookAndFeelAddons
extends BasicLookAndFeelAddons
{
@Override
protected boolean matches() {
return UIManager.getLookAndFeel() instanceof FlatLaf;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
import java.io.InputStream;
import com.formdev.flatlaf.FlatDefaultsAddon;
/**
* SwingX addon for FlatLaf.
*
* @author Karl Tauber
*/
public class FlatSwingXDefaultsAddon
extends FlatDefaultsAddon
{
/**
* Finds SwingX addon .properties file for the given LaF class
* in the same package as this class.
*/
@Override
public InputStream getDefaults( Class<?> lafClass ) {
Class<?> addonClass = this.getClass();
String propertiesName = "/" + addonClass.getPackage().getName().replace( '.', '/' )
+ '/' + lafClass.getSimpleName() + ".properties";
return addonClass.getResourceAsStream( propertiesName );
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXBusyLabel;
import org.jdesktop.swingx.plaf.basic.BasicBusyLabelUI;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.ui.FlatUIUtils;
//TODO scale busy spinner
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXBusyLabel}.
*
* @author Karl Tauber
*/
public class FlatBusyLabelUI
extends BasicBusyLabelUI
{
private Color disabledForeground;
public static ComponentUI createUI( JComponent c ) {
return new FlatBusyLabelUI( (JXBusyLabel) c );
}
public FlatBusyLabelUI( JXBusyLabel busyLabel ) {
super( busyLabel );
}
@Override
protected void installDefaults( JLabel c ) {
super.installDefaults( c );
disabledForeground = UIManager.getColor( "Label.disabledForeground" );
// force recreation of busy painter for correct colors when switching LaF
if( c.getIcon() != null ) {
JXBusyLabel busyLabel = (JXBusyLabel) c;
boolean oldBusy = busyLabel.isBusy();
busyLabel.setBusy( false );
busyLabel.setBusyPainter( null );
busyLabel.setBusy( oldBusy );
}
}
@Override
protected void uninstallDefaults( JLabel c ) {
super.uninstallDefaults( c );
disabledForeground = null;
}
@Override
protected void paintDisabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
int mnemIndex = FlatLaf.isShowMnemonics() ? l.getDisplayedMnemonicIndex() : -1;
g.setColor( disabledForeground );
FlatUIUtils.drawStringUnderlineCharAt( l, g, s, mnemIndex, textX, textY );
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Component;
import org.jdesktop.swingx.JXDatePicker;
import com.formdev.flatlaf.ui.FlatRoundBorder;
/**
* Border for {@link org.jdesktop.swingx.JXDatePicker}.
*
* @author Karl Tauber
*/
public class FlatDatePickerBorder
extends FlatRoundBorder
{
@Override
protected boolean isFocused( Component c ) {
if( c instanceof JXDatePicker )
return ((JXDatePicker)c).getEditor().hasFocus();
return super.isFocused( c );
}
}

View File

@@ -0,0 +1,314 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.geom.Rectangle2D;
import java.text.ParseException;
import java.util.Calendar;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import org.jdesktop.swingx.JXHyperlink;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.calendar.DatePickerFormatter.DatePickerFormatterUIResource;
import org.jdesktop.swingx.plaf.basic.BasicDatePickerUI;
import com.formdev.flatlaf.ui.FlatArrowButton;
import com.formdev.flatlaf.ui.FlatBorder;
import com.formdev.flatlaf.ui.FlatRoundBorder;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.ui.MigLayoutVisualPadding;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXDatePicker}.
*
* @author Karl Tauber
*/
public class FlatDatePickerUI
extends BasicDatePickerUI
{
protected Insets padding;
protected int focusWidth;
protected int arc;
protected String arrowType;
protected Color borderColor;
protected Color disabledBorderColor;
protected Color disabledBackground;
protected Color buttonBackground;
protected Color buttonArrowColor;
protected Color buttonDisabledArrowColor;
protected Color buttonHoverArrowColor;
private JButton popupButton;
public static ComponentUI createUI( JComponent c ) {
return new FlatDatePickerUI();
}
@Override
public void installUI( JComponent c ) {
// must get UI defaults here because installDefaults() is invoked after
// installComponents(), which uses these values to create popup button
padding = UIManager.getInsets( "ComboBox.padding" );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
arrowType = UIManager.getString( "Component.arrowType" );
borderColor = UIManager.getColor( "Component.borderColor" );
disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
buttonBackground = UIManager.getColor( "ComboBox.buttonBackground" );
buttonArrowColor = UIManager.getColor( "ComboBox.buttonArrowColor" );
buttonDisabledArrowColor = UIManager.getColor( "ComboBox.buttonDisabledArrowColor" );
buttonHoverArrowColor = UIManager.getColor( "ComboBox.buttonHoverArrowColor" );
super.installUI( c );
// hack JXDatePicker.TodayPanel colors
// (there is no need to uninstall these changes because only UIResources are used,
// which are automatically replaced when switching LaF)
JPanel linkPanel = datePicker.getLinkPanel();
if( linkPanel instanceof JXPanel && linkPanel.getClass().getName().equals( "org.jdesktop.swingx.JXDatePicker$TodayPanel" ) ) {
((JXPanel)linkPanel).setBackgroundPainter( null );
linkPanel.setBackground( UIManager.getColor( "JXMonthView.background" ) );
if( linkPanel.getComponentCount() >= 1 && linkPanel.getComponent( 0 ) instanceof JXHyperlink ) {
JXHyperlink todayLink = (JXHyperlink) linkPanel.getComponent( 0 );
todayLink.setUnclickedColor( UIManager.getColor( "Hyperlink.linkColor" ) );
todayLink.setClickedColor( UIManager.getColor( "Hyperlink.visitedColor" ) );
}
}
}
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installColors( datePicker, "ComboBox.background", "ComboBox.foreground" );
LookAndFeel.installBorder( datePicker, "JXDatePicker.border" );
LookAndFeel.installProperty( datePicker, "opaque", Boolean.TRUE );
MigLayoutVisualPadding.install( datePicker, focusWidth );
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
borderColor = null;
disabledBorderColor = null;
disabledBackground = null;
buttonBackground = null;
buttonArrowColor = null;
buttonDisabledArrowColor = null;
buttonHoverArrowColor = null;
if( datePicker.getBorder() instanceof UIResource )
datePicker.setBorder( null );
MigLayoutVisualPadding.uninstall( datePicker );
}
@Override
protected JFormattedTextField createEditor() {
JFormattedTextField editor = new DefaultEditor( new DatePickerFormatterUIResource( datePicker.getLocale() ) );
editor.setName( "dateField" );
editor.setBorder( BorderFactory.createEmptyBorder() );
editor.setOpaque( false );
editor.addFocusListener( new FocusListener() {
@Override
public void focusLost( FocusEvent e ) {
if( datePicker != null )
datePicker.repaint();
}
@Override
public void focusGained( FocusEvent e ) {
if( datePicker != null )
datePicker.repaint();
}
} );
return editor;
}
@Override
protected JButton createPopupButton() {
popupButton = new FlatArrowButton( SwingConstants.SOUTH, arrowType, buttonArrowColor,
buttonDisabledArrowColor, buttonHoverArrowColor, null );
popupButton.setName( "popupButton" );
return popupButton;
}
@Override
protected LayoutManager createLayoutManager() {
return new LayoutManager() {
@Override
public void addLayoutComponent( String name, Component comp ) {}
@Override
public void removeLayoutComponent( Component comp ) {}
@Override
public Dimension preferredLayoutSize( Container parent ) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize( Container parent ) {
return parent.getMinimumSize();
}
@Override
public void layoutContainer( Container parent ) {
Insets insets = datePicker.getInsets();
int x = insets.left;
int y = insets.top;
int width = datePicker.getWidth() - insets.left - insets.right;
int height = datePicker.getHeight() - insets.top - insets.bottom;
int popupButtonWidth = popupButton != null ? height : 0;
boolean ltr = datePicker.getComponentOrientation().isLeftToRight();
Rectangle r = new Rectangle( x + (ltr ? 0 : popupButtonWidth), y, width - popupButtonWidth, height );
r = FlatUIUtils.subtractInsets( r, UIScale.scale( padding ) );
datePicker.getEditor().setBounds( r );
if( popupButton != null )
popupButton.setBounds( x + (ltr ? width - popupButtonWidth : 0), y, popupButtonWidth, height );
}
};
}
@Override
public Dimension getPreferredSize( JComponent c ) {
Dimension dim = datePicker.getEditor().getPreferredSize();
dim = FlatUIUtils.addInsets( dim, UIScale.scale( padding ) );
if( popupButton != null )
dim.width += dim.height;
return FlatUIUtils.addInsets( dim, datePicker.getInsets() );
}
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
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 = popupButton.getX();
int arrowWidth = popupButton.getWidth();
boolean enabled = c.isEnabled();
boolean isLeftToRight = c.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow button
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
}
paint( g, c );
}
//---- class DefaultEditor ------------------------------------------------
private class DefaultEditor
extends JFormattedTextField
implements UIResource
{
DefaultEditor( AbstractFormatter formatter ) {
super( formatter );
// disable Component.minimumWidth
setColumns( 1 );
}
@Override
public Dimension getPreferredSize() {
Dimension prefSize = super.getPreferredSize();
// create date 2000-11-30 that is used for minimum width calculation
Calendar calendar = Calendar.getInstance( datePicker.getLocale() );
calendar.set( 2000, 11, 30 );
try {
AbstractFormatter formatter = getFormatter();
String str = formatter.valueToString( calendar.getTime() );
Insets insets = getInsets();
FontMetrics metrics = getFontMetrics( getFont() );
int minWidth = metrics.stringWidth( str ) + insets.left + insets.right + 2;
return new Dimension( Math.max( minWidth, prefSize.width ), prefSize.height );
} catch( ParseException ex ) {
// ignore
return prefSize;
}
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXHeader;
import org.jdesktop.swingx.plaf.basic.BasicHeaderUI;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXHeader}.
*
* @author Karl Tauber
*/
public class FlatHeaderUI
extends BasicHeaderUI
{
public static ComponentUI createUI( JComponent c ) {
return new FlatHeaderUI();
}
@Override
protected void installComponents( JXHeader header ) {
super.installComponents( header );
scaleLayout( header );
}
@Override
protected void onPropertyChange( JXHeader h, String propertyName, Object oldValue, Object newValue ) {
super.onPropertyChange( h, propertyName, oldValue, newValue );
if( "iconPosition".equals( propertyName ) )
scaleLayout( h );
}
private void scaleLayout( JXHeader header ) {
if( UIScale.getUserScaleFactor() == 1f )
return;
LayoutManager layout = header.getLayout();
if( !(layout instanceof GridBagLayout) )
return;
GridBagLayout gbl = (GridBagLayout) layout;
for( Component c : header.getComponents() ) {
GridBagConstraints cons = gbl.getConstraints( c );
cons.insets = UIScale.scale( cons.insets );
gbl.setConstraints( c, cons );
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.plaf.basic.BasicHyperlinkUI;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXHyperlink}.
*
* @uiDefault Hyperlink.disabledText Color
*
* @author Karl Tauber
*/
public class FlatHyperlinkUI
extends BasicHyperlinkUI
{
protected Color disabledText;
public static ComponentUI createUI( JComponent c ) {
return new FlatHyperlinkUI();
}
@Override
protected void installDefaults( AbstractButton b ) {
super.installDefaults( b );
disabledText = UIManager.getColor( "Hyperlink.disabledText" );
}
@Override
protected void uninstallDefaults( AbstractButton b ) {
super.uninstallDefaults( b );
disabledText = null;
}
@Override
public void paint( Graphics g, JComponent c ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paint( g, c );
}
@Override
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
FlatButtonUI.paintText( g, b, textRect, text, b.isEnabled() ? b.getForeground() : disabledText );
if( b.getModel().isRollover() )
paintUnderline( g, textRect );
}
private void paintUnderline( Graphics g, Rectangle rect ) {
int descent = g.getFontMetrics().getDescent();
((Graphics2D)g).fill( new Rectangle2D.Float(
rect.x, (rect.y + rect.height) - descent + UIScale.scale( 1f ),
rect.width, UIScale.scale( 1f ) ) );
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Shape;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import com.formdev.flatlaf.icons.FlatAbstractIcon;
import com.formdev.flatlaf.ui.FlatArrowButton;
/**
* "month down" icon for {@link org.jdesktop.swingx.JXMonthView}.
*
* @uiDefault Component.arrowType String triangle (default) or chevron
* @uiDefault JXMonthView.arrowColor Color
* @uiDefault JXMonthView.disabledArrowColor Color
*
* @author Karl Tauber
*/
public class FlatMonthDownIcon
extends FlatAbstractIcon
{
protected final boolean chevron = "chevron".equals( UIManager.getString( "Component.arrowType" ) );
protected final Color arrowColor = UIManager.getColor( "JXMonthView.arrowColor" );
protected final Color disabledArrowColor = UIManager.getColor( "JXMonthView.disabledArrowColor" );
private final int direction;
public FlatMonthDownIcon() {
this( SwingConstants.WEST );
}
protected FlatMonthDownIcon( int direction ) {
super( 20, 20, null );
this.direction = direction;
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
int h = chevron ? 4 : 5;
int w = chevron ? 8 : 9;
int x = Math.round( (width - h) / 2f );
int y = Math.round( (height - w) / 2f );
g.setColor( c.isEnabled() ? arrowColor : disabledArrowColor );
g.translate( x, y );
Shape arrowShape = FlatArrowButton.createArrowShape( direction, chevron, w, h );
if( chevron ) {
// chevron arrow
g.setStroke( new BasicStroke( 1f ) );
g.draw( arrowShape );
} else {
// triangle arrow
g.fill( arrowShape );
}
g.translate( -x, -y );
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import javax.swing.SwingConstants;
/**
* "month up" icon for {@link org.jdesktop.swingx.JXMonthView}.
*
* @author Karl Tauber
*/
public class FlatMonthUpIcon
extends FlatMonthDownIcon
{
public FlatMonthUpIcon() {
super( SwingConstants.EAST );
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import java.awt.Insets;
import java.util.Calendar;
import javax.swing.JComponent;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.plaf.basic.BasicMonthViewUI;
import org.jdesktop.swingx.plaf.basic.CalendarRenderingHandler;
import org.jdesktop.swingx.plaf.basic.CalendarState;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXMonthView}.
*
* @author Karl Tauber
*/
public class FlatMonthViewUI
extends BasicMonthViewUI
{
public static ComponentUI createUI( JComponent c ) {
return new FlatMonthViewUI();
}
@Override
protected CalendarRenderingHandler createRenderingHandler() {
return new FlatRenderingHandler();
}
//---- class FlatRenderingHandler -----------------------------------------
private static class FlatRenderingHandler
extends RenderingHandler
{
@Override
public JComponent prepareRenderingComponent( JXMonthView monthView, Calendar calendar,
CalendarState dayState )
{
JComponent c = super.prepareRenderingComponent( monthView, calendar, dayState );
int px = monthView.getBoxPaddingX();
int py = monthView.getBoxPaddingY();
// scale borders
Border border = null;
if( dayState == CalendarState.TITLE && monthView.isTraversable() ) {
Border b = c.getBorder();
if( b instanceof CompoundBorder && ((CompoundBorder)b).getInsideBorder() instanceof EmptyBorder )
border = new CompoundBorder( ((CompoundBorder)b).getOutsideBorder(), new FlatEmptyBorder( py * 2, 0, py * 2, 0 ) );
} else if( dayState == CalendarState.TODAY )
border = new FlatLineBorder( new Insets( py, px, py, px ), monthView.getTodayBackground() );
if( border == null )
border = new FlatEmptyBorder( py, px, py, px );
c.setBorder( border );
return c;
}
}
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.plaf.basic.BasicTaskPaneUI;
import com.formdev.flatlaf.ui.FlatArrowButton;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXTaskPane}.
*
* @author Karl Tauber
*/
public class FlatTaskPaneUI
extends BasicTaskPaneUI
{
private Color background;
public static ComponentUI createUI( JComponent c ) {
return new FlatTaskPaneUI();
}
@Override
protected void installDefaults() {
if( group.getContentPane() instanceof JComponent ) {
// remove default SwingX content border, which may be still set when switching LaF
JComponent content = (JComponent) group.getContentPane();
Border contentBorder = content.getBorder();
if( contentBorder instanceof CompoundBorder &&
((CompoundBorder)contentBorder).getOutsideBorder() instanceof BasicTaskPaneUI.ContentPaneBorder &&
((CompoundBorder)contentBorder).getInsideBorder() instanceof EmptyBorder )
{
content.setBorder( null );
}
// set non-UIResource color to background to avoid that it is lost when switching LaF
background = UIManager.getColor( "TaskPane.background" );
Color bg = content.getBackground();
if( bg == null || bg instanceof UIResource ) {
content.setBackground( new Color( background.getRGB(), true ) );
}
}
roundHeight = FlatUIUtils.getUIInt( "TaskPane.roundHeight", UIManager.getInt( "Component.arc" ) );
super.installDefaults();
}
@Override
public void uninstallUI( JComponent c ) {
if( group.getContentPane() instanceof JComponent ) {
// uninstall our content border, because it does not implement UIResource,
// to alloy other LaF to install its own border
JComponent content = (JComponent) group.getContentPane();
if( content.getBorder() instanceof FlatContentPaneBorder )
content.setBorder( null );
// replace our non-UIResouce background with UIResouce background
// to allow next LaF to overwrite it
if( background.equals( content.getBackground() ) )
content.setBackground( background );
background = null;
}
super.uninstallUI( c );
}
@Override
protected int getTitleHeight( Component c ) {
return Math.max( super.getTitleHeight( c ), UIScale.scale( titleHeight ) );
}
@Override
protected int getRoundHeight() {
return UIScale.scale( roundHeight );
}
@Override
protected Border createPaneBorder() {
return new FlatPaneBorder();
}
@Override
protected Border createContentPaneBorder() {
return new FlatContentPaneBorder( UIManager.getColor( "TaskPane.borderColor" ),
UIManager.getInsets( "TaskPane.contentInsets" ) );
}
//---- class FlatContentPaneBorder ----------------------------------------
/**
* The content pane border.
*/
private static class FlatContentPaneBorder
extends EmptyBorder
{
Color color;
FlatContentPaneBorder( Color color, Insets insets ) {
super( insets );
this.color = color;
// add space for the line border
left++;
right++;
bottom++;
}
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
if( color == null )
return;
FlatUIUtils.setRenderingHints( (Graphics2D) g );
g.setColor( color );
float lineWidth = UIScale.scale( 1f );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Rectangle2D.Float( x, y, width, height ), false );
path.append( new Rectangle2D.Float( x + lineWidth, y, width - (lineWidth * 2), height - lineWidth ), false );
((Graphics2D)g).fill( path );
}
@Override
public Insets getBorderInsets() {
return new Insets( scale( top ), scale( left ), scale( bottom ), scale( right ) );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
insets.left = scale( left );
insets.top = scale( top );
insets.right = scale( right );
insets.bottom = scale( bottom );
return insets;
}
}
//---- class FlatPaneBorder -----------------------------------------------
private class FlatPaneBorder
extends PaneBorder
{
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paintBorder( c, g, x, y, width, height );
}
@Override
protected void paintTitleBackground( JXTaskPane group, Graphics g ) {
int width = group.getWidth();
int height = getTitleHeight( group ) ;
float arc = UIScale.scale( (float) roundHeight );
float lineWidth = UIScale.scale( 1f );
// paint background
g.setColor( group.isSpecial() ? specialTitleBackground : titleBackgroundGradientStart );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectanglePath( lineWidth, lineWidth,
width - (lineWidth * 2), height - (lineWidth * 2), arc - lineWidth, arc - lineWidth, 0, 0 ) );
// paint border
if( borderColor != null ) {
g.setColor( borderColor );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectangle( 0, 0, width, height, lineWidth, arc, arc, 0, 0 ) );
}
}
@Override
protected void paintExpandedControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
g.setColor( getPaintColor( group ) );
paintChevronControls( group, g, x, y, width, height );
}
@Override
protected void paintChevronControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
Graphics2D g2 = (Graphics2D) g;
// scale chevron size
float cw = scale( 6f );
float ch = scale( 3f );
// create arrow shape
int direction = group.isCollapsed() ? SwingConstants.SOUTH : SwingConstants.NORTH;
Shape arrowShape = FlatArrowButton.createArrowShape( direction, true, cw, ch );
// fix position of controls
x = group.getComponentOrientation().isLeftToRight() ? (group.getWidth() - width - y) : y;
// compute chevron position
int cx = (int) (x + width / 2 - cw / 2);
int cy = (int) (y + (height / 2 - ch));
float offset = ch + UIScale.scale( 1f );
// set stroke with scaled width
g2.setStroke( new BasicStroke( scale( 1f ) ) );
// paint
g2.translate( cx, cy );
g2.draw( arrowShape );
g2.translate( 0, offset );
g2.draw( arrowShape );
g2.translate( -cx, -(cy + offset) );
}
@Override
protected void paintTitle( JXTaskPane group, Graphics g, Color textColor,
int x, int y, int width, int height )
{
// scale title position
int titleX = UIScale.scale( 3 );
int titleWidth = group.getWidth() - getTitleHeight(group) - titleX;
if( !group.getComponentOrientation().isLeftToRight() ) {
// right-to-left
titleX = group.getWidth() - titleX - titleWidth;
}
super.paintTitle( group, g, textColor, titleX, y, titleWidth, height );
}
@Override
protected void paintFocus( Graphics g, Color paintColor, int x, int y, int width, int height ) {
// scale focus rectangle
int sx = UIScale.scale( x );
int sy = UIScale.scale( y );
int swidth = width - (sx - x) * 2;
int sheight = height - (sy - y) * 2;
super.paintFocus( g, paintColor, sx, sy, swidth, sheight );
}
@Override
protected boolean isMouseOverBorder() {
return true;
}
}
}

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.swingx.FlatSwingXDefaultsAddon

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.swingx.FlatLookAndFeelAddons

View File

@@ -0,0 +1,69 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- BusyLabel ----
JXBusyLabel.baseColor=777777
JXBusyLabel.highlightColor=e0e0e0
#---- Header ----
JXHeader.background=@background
JXHeader.startBackground=4c5052
#---- Hyperlink ----
Hyperlink.linkColor=589df6
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- MonthView ----
JXMonthView.background=@textComponentBackground
JXMonthView.monthStringBackground=4c5052
JXMonthView.monthStringForeground=@foreground
JXMonthView.daysOfTheWeekForeground=aaaaaa
JXMonthView.weekOfTheYearForeground=888888
JXMonthView.unselectableDayForeground=E05555
JXMonthView.selectedBackground=@selectionBackground
JXMonthView.flaggedDayForeground=E05555
JXMonthView.leadingDayForeground=@disabledText
JXMonthView.trailingDayForeground=@disabledText
JXMonthView.arrowColor=@foreground
JXMonthView.disabledArrowColor=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=3E434C
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=4c5052
TaskPane.titleForeground=@foreground
TaskPane.titleOver=888888
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

@@ -0,0 +1,35 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- UI delegates ----
BusyLabelUI=com.formdev.flatlaf.swingx.ui.FlatBusyLabelUI
DatePickerUI=com.formdev.flatlaf.swingx.ui.FlatDatePickerUI
HeaderUI=com.formdev.flatlaf.swingx.ui.FlatHeaderUI
HyperlinkUI=com.formdev.flatlaf.swingx.ui.FlatHyperlinkUI
MonthViewUI=com.formdev.flatlaf.swingx.ui.FlatMonthViewUI
swingx/TaskPaneUI=com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI
#---- DatePicker ----
JXDatePicker.border=com.formdev.flatlaf.swingx.ui.FlatDatePickerBorder
#---- MonthView ----
JXMonthView.monthDownFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthDownIcon
JXMonthView.monthUpFileName={icon}com.formdev.flatlaf.swingx.ui.FlatMonthUpIcon

View File

@@ -0,0 +1,69 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- BusyLabel ----
JXBusyLabel.baseColor=c4c4c4
JXBusyLabel.highlightColor=808080
#---- Header ----
JXHeader.background=@background
JXHeader.startBackground=ffffff
#---- Hyperlink ----
Hyperlink.linkColor=4a78c2
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- MonthView ----
JXMonthView.background=@textComponentBackground
JXMonthView.monthStringBackground=dfdfdf
JXMonthView.monthStringForeground=@foreground
JXMonthView.daysOfTheWeekForeground=444444
JXMonthView.weekOfTheYearForeground=666666
JXMonthView.unselectableDayForeground=E02222
JXMonthView.selectedBackground=B9CEF8
JXMonthView.flaggedDayForeground=E02222
JXMonthView.leadingDayForeground=@disabledText
JXMonthView.trailingDayForeground=@disabledText
JXMonthView.arrowColor=@foreground
JXMonthView.disabledArrowColor=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=E6EBF0
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=dfdfdf
TaskPane.titleForeground=222222
TaskPane.titleOver=666666
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

@@ -0,0 +1,321 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
import java.awt.*;
import java.util.Calendar;
import java.util.Date;
import javax.swing.*;
import net.miginfocom.swing.*;
import org.jdesktop.swingx.*;
import com.formdev.flatlaf.FlatTestFrame;
/**
* @author Karl Tauber
*/
public class FlatSwingXTest
extends JPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSwingXTest" );
frame.showFrame( new FlatSwingXTest() );
}
FlatSwingXTest() {
initComponents();
Calendar calendar = Calendar.getInstance();
calendar.set( Calendar.DAY_OF_MONTH, 2 );
monthView1.setSelectionDate( calendar.getTime() );
calendar.set( Calendar.DAY_OF_MONTH, 9 );
monthView1.setFlaggedDates( calendar.getTime() );
calendar.set( Calendar.DAY_OF_MONTH, 16 );
monthView1.setUnselectableDates( calendar.getTime() );
}
private void busyChanged() {
boolean busy = busyCheckBox.isSelected();
xBusyLabel1.setBusy( busy );
xBusyLabel2.setBusy( busy );
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel label1 = new JLabel();
JLabel label3 = new JLabel();
JLabel datePickerLabel = new JLabel();
JXDatePicker xDatePicker1 = new JXDatePicker();
JXDatePicker xDatePicker2 = new JXDatePicker();
JLabel label4 = new JLabel();
JLabel label5 = new JLabel();
JXDatePicker xDatePicker3 = new JXDatePicker();
JXDatePicker xDatePicker4 = new JXDatePicker();
JLabel monthViewLabel = new JLabel();
monthView1 = new JXMonthView();
monthView2 = new JXMonthView();
JLabel hyperlinkLabel = new JLabel();
JXHyperlink xHyperlink1 = new JXHyperlink();
JXHyperlink xHyperlink2 = new JXHyperlink();
JLabel label2 = new JLabel();
xBusyLabel1 = new JXBusyLabel();
xBusyLabel2 = new JXBusyLabel();
busyCheckBox = new JCheckBox();
JPanel panel2 = new JPanel();
JLabel taskPaneContainerLabel = new JLabel();
JLabel taskPaneLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JXTaskPaneContainer xTaskPaneContainer1 = new JXTaskPaneContainer();
JXTaskPane xTaskPane3 = new JXTaskPane();
JXHyperlink xHyperlink3 = new JXHyperlink();
JXHyperlink xHyperlink4 = new JXHyperlink();
JXHyperlink xHyperlink5 = new JXHyperlink();
JXTaskPane xTaskPane4 = new JXTaskPane();
JXHyperlink xHyperlink6 = new JXHyperlink();
JXHyperlink xHyperlink7 = new JXHyperlink();
JXTaskPane xTaskPane5 = new JXTaskPane();
JXHyperlink xHyperlink8 = new JXHyperlink();
JXTaskPane xTaskPane6 = new JXTaskPane();
JXHyperlink xHyperlink9 = new JXHyperlink();
JXHyperlink xHyperlink10 = new JXHyperlink();
JLabel headerLabel = new JLabel();
JXHeader xHeader1 = new JXHeader();
//======== this ========
setLayout(new MigLayout(
"hidemode 3,ltr",
// columns
"[left]" +
"[]" +
"[]" +
"[fill]",
// rows
"[]0" +
"[]" +
"[]0" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- label1 ----
label1.setText("enabled");
add(label1, "cell 1 0");
//---- label3 ----
label3.setText("disabled");
add(label3, "cell 2 0");
//---- datePickerLabel ----
datePickerLabel.setText("JXDatePicker:");
add(datePickerLabel, "cell 0 1");
add(xDatePicker1, "cell 1 1");
//---- xDatePicker2 ----
xDatePicker2.setEnabled(false);
add(xDatePicker2, "cell 2 1");
//---- label4 ----
label4.setText("not editable");
add(label4, "cell 1 2");
//---- label5 ----
label5.setText("not editable disabled");
add(label5, "cell 2 2");
//---- xDatePicker3 ----
xDatePicker3.setEditable(false);
add(xDatePicker3, "cell 1 3");
//---- xDatePicker4 ----
xDatePicker4.setEnabled(false);
xDatePicker4.setEditable(false);
add(xDatePicker4, "cell 2 3");
//---- monthViewLabel ----
monthViewLabel.setText("JXMonthView:");
add(monthViewLabel, "cell 0 4,aligny top,growy 0");
//---- monthView1 ----
monthView1.setTraversable(true);
monthView1.setShowingLeadingDays(true);
monthView1.setShowingTrailingDays(true);
monthView1.setShowingWeekNumber(true);
add(monthView1, "cell 1 4");
//---- monthView2 ----
monthView2.setTraversable(true);
monthView2.setShowingLeadingDays(true);
monthView2.setShowingTrailingDays(true);
monthView2.setShowingWeekNumber(true);
monthView2.setEnabled(false);
add(monthView2, "cell 2 4");
//---- hyperlinkLabel ----
hyperlinkLabel.setText("JXHyperlink:");
add(hyperlinkLabel, "cell 0 5");
//---- xHyperlink1 ----
xHyperlink1.setText("enabled");
add(xHyperlink1, "cell 1 5");
//---- xHyperlink2 ----
xHyperlink2.setText("disabled");
xHyperlink2.setEnabled(false);
add(xHyperlink2, "cell 2 5");
//---- label2 ----
label2.setText("JXBusyLabel:");
add(label2, "cell 0 6");
//---- xBusyLabel1 ----
xBusyLabel1.setText("enabled");
add(xBusyLabel1, "cell 1 6");
//---- xBusyLabel2 ----
xBusyLabel2.setText("disabled");
xBusyLabel2.setEnabled(false);
add(xBusyLabel2, "cell 2 6,growx");
//---- busyCheckBox ----
busyCheckBox.setText("busy");
busyCheckBox.setMnemonic('B');
busyCheckBox.addActionListener(e -> busyChanged());
add(busyCheckBox, "cell 2 6");
//======== panel2 ========
{
panel2.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[fill]",
// rows
"[]" +
"[]" +
"[]"));
//---- taskPaneContainerLabel ----
taskPaneContainerLabel.setText("JXTaskPaneContainer:");
panel2.add(taskPaneContainerLabel, "cell 0 0");
//---- taskPaneLabel ----
taskPaneLabel.setText("JXTaskPane:");
panel2.add(taskPaneLabel, "cell 0 1");
//======== scrollPane1 ========
{
//======== xTaskPaneContainer1 ========
{
//======== xTaskPane3 ========
{
xTaskPane3.setTitle("Basic Tasks");
Container xTaskPane3ContentPane = xTaskPane3.getContentPane();
//---- xHyperlink3 ----
xHyperlink3.setText("New");
xTaskPane3ContentPane.add(xHyperlink3);
//---- xHyperlink4 ----
xHyperlink4.setText("Open");
xTaskPane3ContentPane.add(xHyperlink4);
//---- xHyperlink5 ----
xHyperlink5.setText("Save");
xTaskPane3ContentPane.add(xHyperlink5);
}
xTaskPaneContainer1.add(xTaskPane3);
//======== xTaskPane4 ========
{
xTaskPane4.setTitle("Other Tasks");
xTaskPane4.setIcon(UIManager.getIcon("Tree.closedIcon"));
Container xTaskPane4ContentPane = xTaskPane4.getContentPane();
//---- xHyperlink6 ----
xHyperlink6.setText("Duplicate");
xTaskPane4ContentPane.add(xHyperlink6);
//---- xHyperlink7 ----
xHyperlink7.setText("Delete");
xTaskPane4ContentPane.add(xHyperlink7);
}
xTaskPaneContainer1.add(xTaskPane4);
//======== xTaskPane5 ========
{
xTaskPane5.setTitle("Special Tasks");
xTaskPane5.setSpecial(true);
Container xTaskPane5ContentPane = xTaskPane5.getContentPane();
//---- xHyperlink8 ----
xHyperlink8.setText("Go to space");
xTaskPane5ContentPane.add(xHyperlink8);
}
xTaskPaneContainer1.add(xTaskPane5);
//======== xTaskPane6 ========
{
xTaskPane6.setTitle("Collapsed");
xTaskPane6.setCollapsed(true);
Container xTaskPane6ContentPane = xTaskPane6.getContentPane();
//---- xHyperlink9 ----
xHyperlink9.setText("text");
xTaskPane6ContentPane.add(xHyperlink9);
//---- xHyperlink10 ----
xHyperlink10.setText("text");
xTaskPane6ContentPane.add(xHyperlink10);
}
xTaskPaneContainer1.add(xTaskPane6);
}
scrollPane1.setViewportView(xTaskPaneContainer1);
}
panel2.add(scrollPane1, "cell 0 2,width 150,height 350");
}
add(panel2, "cell 3 0 1 8,aligny top,growy 0");
//---- headerLabel ----
headerLabel.setText("JXHeader:");
add(headerLabel, "cell 0 7,aligny top,growy 0");
//---- xHeader1 ----
xHeader1.setTitle("Title");
xHeader1.setDescription("Description\nMore description");
xHeader1.setIcon(new ImageIcon(getClass().getResource("/org/jdesktop/swingx/plaf/windows/resources/tipoftheday.png")));
add(xHeader1, "cell 1 7 2 1,width 200");
// JFormDesigner - End of component initialization //GEN-END:initComponents
xDatePicker1.setDate( new Date() );
xDatePicker2.setDate( new Date() );
xDatePicker3.setDate( new Date() );
xDatePicker4.setDate( new Date() );
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JXMonthView monthView1;
private JXMonthView monthView2;
private JXBusyLabel xBusyLabel1;
private JXBusyLabel xBusyLabel2;
private JCheckBox busyCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,254 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3,ltr"
"$columnConstraints": "[left][][][fill]"
"$rowConstraints": "[]0[][]0[][][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "enabled"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "disabled"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "datePickerLabel"
"text": "JXDatePicker:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "org.jdesktop.swingx.JXDatePicker" ) {
name: "xDatePicker1"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "org.jdesktop.swingx.JXDatePicker" ) {
name: "xDatePicker2"
"enabled": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "not editable"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label5"
"text": "not editable disabled"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 2"
} )
add( new FormComponent( "org.jdesktop.swingx.JXDatePicker" ) {
name: "xDatePicker3"
"editable": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "org.jdesktop.swingx.JXDatePicker" ) {
name: "xDatePicker4"
"enabled": false
"editable": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 3"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "monthViewLabel"
"text": "JXMonthView:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4,aligny top,growy 0"
} )
add( new FormComponent( "org.jdesktop.swingx.JXMonthView" ) {
name: "monthView1"
"traversable": true
"showingLeadingDays": true
"showingTrailingDays": true
"showingWeekNumber": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
add( new FormComponent( "org.jdesktop.swingx.JXMonthView" ) {
name: "monthView2"
"traversable": true
"showingLeadingDays": true
"showingTrailingDays": true
"showingWeekNumber": true
"enabled": false
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 4"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "hyperlinkLabel"
"text": "JXHyperlink:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink1"
"text": "enabled"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink2"
"text": "disabled"
"enabled": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 5"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "JXBusyLabel:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6"
} )
add( new FormComponent( "org.jdesktop.swingx.JXBusyLabel" ) {
name: "xBusyLabel1"
"text": "enabled"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6"
} )
add( new FormComponent( "org.jdesktop.swingx.JXBusyLabel" ) {
name: "xBusyLabel2"
"text": "disabled"
"enabled": false
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 6,growx"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "busyCheckBox"
"text": "busy"
"mnemonic": 66
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "busyChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 6"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][]"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel2"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "taskPaneContainerLabel"
"text": "JXTaskPaneContainer:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "taskPaneLabel"
"text": "JXTaskPane:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane1"
add( new FormContainer( "org.jdesktop.swingx.JXTaskPaneContainer", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPaneContainer1"
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane3"
"title": "Basic Tasks"
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink3"
"text": "New"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink4"
"text": "Open"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink5"
"text": "Save"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane4"
"title": "Other Tasks"
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.closedIcon" )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink6"
"text": "Duplicate"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink7"
"text": "Delete"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane5"
"title": "Special Tasks"
"special": true
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink8"
"text": "Go to space"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane6"
"title": "Collapsed"
"collapsed": true
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink9"
"text": "text"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink10"
"text": "text"
} )
} )
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2,width 150,height 350"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 0 1 8,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "headerLabel"
"text": "JXHeader:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 7,aligny top,growy 0"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHeader" ) {
name: "xHeader1"
"title": "Title"
"description": "Description\nMore description"
"icon": new com.jformdesigner.model.SwingIcon( 0, "/org/jdesktop/swingx/plaf/windows/resources/tipoftheday.png" )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7 2 1,width 200"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 700, 600 )
} )
}
}

View File

@@ -0,0 +1,71 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- BusyLabel ----
JXBusyLabel.baseColor=00ff00
JXBusyLabel.highlightColor=ff0000
#---- Header ----
JXHeader.background=ff8888
JXHeader.startBackground=ffcccc
JXHeader.titleForeground=0000ff
JXHeader.descriptionForeground=ff0000
#---- Hyperlink ----
Hyperlink.linkColor=ff0000
Hyperlink.visitedColor=0000ff
Hyperlink.disabledText=000088
#---- MonthView ----
JXMonthView.background=@textComponentBackground
JXMonthView.monthStringBackground=00ff00
JXMonthView.monthStringForeground=0000ff
JXMonthView.daysOfTheWeekForeground=00ff00
JXMonthView.weekOfTheYearForeground=0000ff
JXMonthView.unselectableDayForeground=0000ff
JXMonthView.selectedBackground=aaffaa
JXMonthView.flaggedDayForeground=00ffff
JXMonthView.leadingDayForeground=c0c0c0
JXMonthView.trailingDayForeground=c0c0c0
JXMonthView.arrowColor=0000ff
JXMonthView.disabledArrowColor=ABABAB
#---- TaskPaneContainer ----
TaskPaneContainer.background=ff8888
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=00ff00
TaskPane.borderColor=0000ff
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=ffff00
TaskPane.titleForeground=ff00ff
TaskPane.titleOver=0000aa
TaskPane.specialTitleBackground=00ffff
TaskPane.specialTitleForeground=444444
TaskPane.specialTitleOver=dd0000

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -17,4 +17,5 @@
rootProject.name = "FlatLaf" rootProject.name = "FlatLaf"
include( "flatlaf-core" ) include( "flatlaf-core" )
include( "flatlaf-swingx" )
include( "flatlaf-demo" ) include( "flatlaf-demo" )