Compare commits

...

26 Commits
0.15 ... 0.17

Author SHA1 Message Date
Karl Tauber
2e0fde464d release 0.17 2019-10-27 12:29:12 +01:00
Karl Tauber
9bf0124950 FlatBorder: replaced Paint with Color 2019-10-27 12:27:31 +01:00
Karl Tauber
eaa6db1d19 Table: fixed missing upper right corner (e.g. in SwingX JXTable with column control visible) 2019-10-27 12:25:39 +01:00
Karl Tauber
2ec142f000 Button: hover and pressed background colors are now derived from actual button background color (issue #21) 2019-10-27 11:03:40 +01:00
Karl Tauber
ec572436a9 extracted properties file parsing to new class UIDefaultsLoader 2019-10-25 23:07:44 +02:00
Karl Tauber
6e5e548c9d Testing: fixed content panel insets and removed 5,5 gaps 2019-10-25 10:44:24 +02:00
Karl Tauber
61c3bbad60 ComboBox and Spinner:
- make child components explicitly non-opaque
- paint parent background only if necessary
2019-10-25 10:28:24 +02:00
Karl Tauber
bc10c4e871 Made JComboBox, JProgressBar, JSpinner and JXDatePicker non-opaque.
`JPasswordField`, `JScrollPane` and `JTextField` are non-opaque if they have
an outside focus border (e.g. IntelliJ and Darcula themes).
(issues #20 and #17)
2019-10-25 10:28:18 +02:00
Karl Tauber
8b8d84c2a3 TextField and PasswordField: reduced duplicate code 2019-10-24 20:47:31 +02:00
Karl Tauber
5743b5d59f CheckBox: removed accidentally checked in debug output 2019-10-24 18:07:22 +02:00
Karl Tauber
9450ba5e46 Extras: fixed link in README.md 2019-10-24 15:31:13 +02:00
Karl Tauber
cfcbf3e61c CheckBox:
- compute focus border arc based on Component.focusWidth
- allow specifying border arc in UI defaults (CheckBox.arc)
2019-10-24 14:28:50 +02:00
Karl Tauber
136481c110 Testing: added "opaque" checkbox to test apps 2019-10-24 12:44:16 +02:00
Karl Tauber
7f43b3003c TriStateCheckBox component added 2019-10-24 12:36:40 +02:00
Karl Tauber
1b0c2687c8 Testing: added "background" checkbox to test apps 2019-10-24 10:52:53 +02:00
Karl Tauber
aeb80f862b build.gradle.kts: depend task "assemble" on "sourcesJar" and "javadocJar" so that they are built on Travic CI to file problems early (previously those tasks were build only just before publishing) 2019-10-23 17:06:25 +02:00
Karl Tauber
1de367e19e moved testing applications from src/test to new project flatlaf-testing (part 2) 2019-10-23 16:44:39 +02:00
Karl Tauber
62895a602f moved testing applications from src/test to new project flatlaf-testing (part 1) 2019-10-23 16:44:19 +02:00
Karl Tauber
6438e890bb release 0.16 2019-10-23 10:46:46 +02:00
Karl Tauber
7d72b13ac9 made JButton, JCheckBox, JRadioButton, JToggleButton and JSlider non-opaque (#20) 2019-10-23 10:36:33 +02:00
Karl Tauber
a2e21cb07b fixed Java 9 module descriptor (broken since 0.14) 2019-10-23 09:55:55 +02:00
Karl Tauber
06766cb4db Demo: missing SwingUtilities.invokeLater() added 2019-10-23 09:03:08 +02:00
Karl Tauber
72e8ab70a3 Demo: tooltips added to toolbar buttons 2019-10-22 12:09:04 +02:00
Karl Tauber
0f38af5922 ComboBox: right-to-left fixes (#18) 2019-10-22 12:07:23 +02:00
Karl Tauber
4181759008 right-to-left fixes:
-Slider: colored track (if ticks and labels are hidden) was on the left side of the thumb
- ToolTip: multi-line text was not aligned to the right

(issue #18)
2019-10-21 22:12:51 +02:00
Karl Tauber
fff0e5e946 fixed FlatTestLaf (broken by commit 342b932f9e) 2019-10-21 20:11:35 +02:00
65 changed files with 2143 additions and 757 deletions

View File

@@ -1,6 +1,30 @@
FlatLaf Change Log
==================
## 0.17
- CheckBox: Support painting a third state (set client property
"JButton.selectedState" to "indeterminate").
- `TriStateCheckBox` component added (see [FlatLaf Extras](flatlaf-extras)).
- Made `JComboBox`, `JProgressBar`, `JSpinner` and `JXDatePicker` non-opaque.
`JPasswordField`, `JScrollPane` and `JTextField` are non-opaque if they have
an outside focus border (e.g. IntelliJ and Darcula themes). (issues #20 and
#17)
- Button: Hover and pressed background colors are now derived from actual button
background color. (issue #21)
- Table: Fixed missing upper right corner (e.g. in SwingX JXTable with column
control visible).
## 0.16
- Made some fixes for right-to-left support in ComboBox, Slider and ToolTip.
(issue #18)
- Fixed Java 9 module descriptor (broken since 0.14).
- Made `JButton`, `JCheckBox`, `JRadioButton`, `JToggleButton` and `JSlider`
non-opaque. (issue #20)
## 0.15
- ToolTip: Improved styling of dark tooltips (darker background, no border).

View File

@@ -35,7 +35,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf
version: 0.15
version: 0.17
Otherwise download `flatlaf-<version>.jar` here:

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
version = "0.15"
version = "0.17"
allprojects {
repositories {

View File

@@ -34,17 +34,19 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
}
}
dependencies {
testImplementation( "com.miglayout:miglayout-swing:5.2" )
testImplementation( "com.jgoodies:jgoodies-forms:1.9.0" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
named<JavaCompile>( "compileModuleInfoJava" ) {
sourceCompatibility = "9"
@@ -88,19 +90,6 @@ tasks {
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 {

View File

@@ -27,6 +27,9 @@ public interface FlatClientProperties
String BUTTON_TYPE = "JButton.buttonType";
String BUTTON_TYPE_HELP = "help";
String SELECTED_STATE = "JButton.selectedState";
String SELECTED_STATE_INDETERMINATE = "indeterminate";
/**
* Checks whether a client property of a component has the given value.
*/

View File

@@ -19,10 +19,8 @@ package com.formdev.flatlaf;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Insets;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
@@ -30,16 +28,7 @@ import java.awt.Window;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
@@ -48,16 +37,9 @@ import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ScaledNumber;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -69,13 +51,6 @@ import com.formdev.flatlaf.util.UIScale;
public abstract class FlatLaf
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 REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?";
private static final String GLOBAL_PREFIX = "*.";
private BasicLookAndFeel base;
private String desktopPropertyName;
@@ -209,7 +184,7 @@ public abstract class FlatLaf
Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null;
initFonts( defaults );
loadDefaultsFromProperties( defaults );
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), defaults );
// use Aqua MenuBarUI if Mac screen menubar is enabled
if( useScreenMenuBar )
@@ -254,291 +229,8 @@ public abstract class FlatLaf
defaults.put( "MenuItem.acceleratorFont", uiFont );
}
/**
* Load properties associated to Flat LaF classes and add to UI defaults.
*
* Each class that extend this class may have its own .properties file
* in the same package as the class. Properties from superclasses are loaded
* first to give subclasses a chance to override defaults.
* E.g. if running FlatDarkLaf, then the FlatLaf.properties is loaded first
* and FlatDarkLaf.properties loaded second.
*/
private void loadDefaultsFromProperties( UIDefaults defaults ) {
// determine classes in class hierarchy in reverse order
ArrayList<Class<?>> lafClasses = new ArrayList<>();
for( Class<?> lafClass = getClass();
FlatLaf.class.isAssignableFrom( lafClass );
lafClass = lafClass.getSuperclass() )
{
lafClasses.add( 0, lafClass );
}
try {
// load properties files
Properties properties = new Properties();
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
for( Class<?> lafClass : lafClasses ) {
// load core properties
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null )
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 -> {
return resolveValue( properties, value );
};
// get globals, which override all other defaults that end with same suffix
HashMap<String, Object> globals = new HashMap<>();
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( !key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver ) );
}
// override UI defaults with globals
for( Object key : defaults.keySet() ) {
if( key instanceof String && ((String)key).contains( "." ) ) {
String skey = (String) key;
String globalKey = skey.substring( skey.lastIndexOf( '.' ) + 1 );
Object globalValue = globals.get( globalKey );
if( globalValue != null )
defaults.put( key, globalValue );
}
}
// add non-global properties to UI defaults
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( key.startsWith( VARIABLE_PREFIX ) || key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
defaults.put( key, parseValue( key, value, resolver ) );
}
} catch( IOException ex ) {
ex.printStackTrace();
}
}
private String resolveValue( Properties properties, String value ) {
if( !value.startsWith( VARIABLE_PREFIX ) )
return value;
if( value.startsWith( REF_PREFIX ) )
value = value.substring( REF_PREFIX.length() );
boolean optional = false;
if( value.startsWith( OPTIONAL_PREFIX ) ) {
value = value.substring( OPTIONAL_PREFIX.length() );
optional = true;
}
String newValue = properties.getProperty( value );
if( newValue == null ) {
if( optional )
return "null";
System.err.println( "variable or reference '" + value + "' not found" );
throw new IllegalArgumentException( value );
}
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 ) {
value = value.trim();
// null, false, true
switch( value ) {
case "null": return null;
case "false": return false;
case "true": return true;
}
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" ) )
valueType = ValueType.BORDER;
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
valueType = ValueType.ICON;
else if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
valueType = ValueType.INSETS;
else if( key.endsWith( "Size" ) )
valueType = ValueType.SIZE;
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
valueType = ValueType.INTEGER;
}
// 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
ColorUIResource color = parseColor( value, false );
if( color != null )
return color;
// integer
Integer integer = parseInteger( value, false );
if( integer != null )
return integer;
// string
return value;
}
}
private Object parseBorder( String value, Function<String, String> resolver ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor]
List<String> parts = split( value, ',' );
Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() == 5)
? parseColor( resolver.apply( parts.get( 4 ) ), true )
: null;
return (LazyValue) t -> {
return (lineColor != null)
? new FlatLineBorder( insets, lineColor )
: new FlatEmptyBorder( insets );
};
} else
return parseInstance( value );
}
private Object parseInstance( String value ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private Insets parseInsets( String value ) {
List<String> numbers = split( value, ',' );
try {
return new InsetsUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ),
Integer.parseInt( numbers.get( 2 ) ),
Integer.parseInt( numbers.get( 3 ) ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid insets '" + value + "'" );
throw ex;
}
}
private Dimension parseSize( String value ) {
List<String> numbers = split( value, ',' );
try {
return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid size '" + value + "'" );
throw ex;
}
}
private ColorUIResource parseColor( String value, boolean reportError ) {
try {
int rgb = Integer.parseInt( value, 16 );
if( value.length() == 6 )
return new ColorUIResource( rgb );
if( value.length() == 8 )
return new ColorUIResource( new Color( rgb, true ) );
if( reportError )
throw new NumberFormatException( value );
} catch( NumberFormatException ex ) {
if( reportError ) {
System.err.println( "invalid color '" + value + "'" );
throw ex;
}
// not a color --> ignore
}
return null;
}
private Integer parseInteger( String value, boolean reportError ) {
try {
return Integer.parseInt( value );
} catch( NumberFormatException ex ) {
if( reportError ) {
System.err.println( "invalid integer '" + value + "'" );
throw ex;
}
}
return null;
}
private ScaledNumber parseScaledNumber( String value ) {
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid integer '" + value + "'" );
throw ex;
}
}
public static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>();
int delimIndex = str.indexOf( delim );
int index = 0;
while( delimIndex >= 0 ) {
strs.add( str.substring( index, delimIndex ) );
index = delimIndex + 1;
delimIndex = str.indexOf( delim, index );
}
strs.add( str.substring( index ) );
return strs;
return UIDefaultsLoader.split( str, delim );
}
private static void reSetLookAndFeel() {

View File

@@ -0,0 +1,407 @@
/*
* 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.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function;
import javax.swing.UIDefaults;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.InsetsUIResource;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ColorFunctions;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.ScaledNumber;
/**
* Load UI defaults from properties files associated to Flat LaF classes and add to UI defaults.
*
* Each class that extend the LaF class may have its own .properties file
* in the same package as the class. Properties from superclasses are loaded
* first to give subclasses a chance to override defaults.
* E.g. if running FlatDarkLaf, then the FlatLaf.properties is loaded first
* and FlatDarkLaf.properties loaded second.
*
* @author Karl Tauber
*/
class UIDefaultsLoader
{
private static final String TYPE_PREFIX = "{";
private static final String TYPE_PREFIX_END = "}";
private static final String VARIABLE_PREFIX = "@";
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?";
private static final String GLOBAL_PREFIX = "*.";
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, UIDefaults defaults ) {
// determine classes in class hierarchy in reverse order
ArrayList<Class<?>> lafClasses = new ArrayList<>();
for( Class<?> lafClass = lookAndFeelClass;
FlatLaf.class.isAssignableFrom( lafClass );
lafClass = lafClass.getSuperclass() )
{
lafClasses.add( 0, lafClass );
}
try {
// load properties files
Properties properties = new Properties();
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
for( Class<?> lafClass : lafClasses ) {
// load core properties
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null )
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 -> {
return resolveValue( properties, value );
};
// get globals, which override all other defaults that end with same suffix
HashMap<String, Object> globals = new HashMap<>();
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( !key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
try {
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
}
// override UI defaults with globals
for( Object key : defaults.keySet() ) {
if( key instanceof String && ((String)key).contains( "." ) ) {
String skey = (String) key;
String globalKey = skey.substring( skey.lastIndexOf( '.' ) + 1 );
Object globalValue = globals.get( globalKey );
if( globalValue != null )
defaults.put( key, globalValue );
}
}
// add non-global properties to UI defaults
for( Map.Entry<Object, Object> e : properties.entrySet() ) {
String key = (String) e.getKey();
if( key.startsWith( VARIABLE_PREFIX ) || key.startsWith( GLOBAL_PREFIX ) )
continue;
String value = resolveValue( properties, (String) e.getValue() );
try {
defaults.put( key, parseValue( key, value, resolver ) );
} catch( RuntimeException ex ) {
logParseError( key, value, ex );
}
}
} catch( IOException ex ) {
ex.printStackTrace();
}
}
private static void logParseError( String key, String value, RuntimeException ex ) {
System.err.println( "Failed to parse: '" + key + '=' + value + '\'' );
System.err.println( " " + ex.getMessage() );
}
private static String resolveValue( Properties properties, String value ) {
if( !value.startsWith( VARIABLE_PREFIX ) )
return value;
if( value.startsWith( REF_PREFIX ) )
value = value.substring( REF_PREFIX.length() );
boolean optional = false;
if( value.startsWith( OPTIONAL_PREFIX ) ) {
value = value.substring( OPTIONAL_PREFIX.length() );
optional = true;
}
String newValue = properties.getProperty( value );
if( newValue == null ) {
if( optional )
return "null";
throw new IllegalArgumentException( "variable or reference '" + value + "' not found" );
}
return resolveValue( properties, newValue );
}
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDNUMBER }
private static Object parseValue( String key, String value, Function<String, String> resolver ) {
value = value.trim();
// null, false, true
switch( value ) {
case "null": return null;
case "false": return false;
case "true": return true;
}
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" ) )
valueType = ValueType.BORDER;
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
valueType = ValueType.ICON;
else if( key.endsWith( ".margin" ) || key.endsWith( ".padding" ) ||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
valueType = ValueType.INSETS;
else if( key.endsWith( "Size" ) )
valueType = ValueType.SIZE;
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
valueType = ValueType.INTEGER;
}
// 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
ColorUIResource color = parseColor( value, false );
if( color != null )
return color;
// integer
Integer integer = parseInteger( value, false );
if( integer != null )
return integer;
// string
return value;
}
}
private static Object parseBorder( String value, Function<String, String> resolver ) {
if( value.indexOf( ',' ) >= 0 ) {
// top,left,bottom,right[,lineColor]
List<String> parts = split( value, ',' );
Insets insets = parseInsets( value );
ColorUIResource lineColor = (parts.size() == 5)
? parseColor( resolver.apply( parts.get( 4 ) ), true )
: null;
return (LazyValue) t -> {
return (lineColor != null)
? new FlatLineBorder( insets, lineColor )
: new FlatEmptyBorder( insets );
};
} else
return parseInstance( value );
}
private static Object parseInstance( String value ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private static Insets parseInsets( String value ) {
List<String> numbers = split( value, ',' );
try {
return new InsetsUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ),
Integer.parseInt( numbers.get( 2 ) ),
Integer.parseInt( numbers.get( 3 ) ) );
} catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid insets '" + value + "'" );
}
}
private static Dimension parseSize( String value ) {
List<String> numbers = split( value, ',' );
try {
return new DimensionUIResource(
Integer.parseInt( numbers.get( 0 ) ),
Integer.parseInt( numbers.get( 1 ) ) );
} catch( NumberFormatException ex ) {
throw new IllegalArgumentException( "invalid size '" + value + "'" );
}
}
private static ColorUIResource parseColor( String value, boolean reportError ) {
if( value.endsWith( ")" ) )
return parseColorFunctions( value, reportError );
try {
int rgb = Integer.parseInt( value, 16 );
if( value.length() == 6 )
return new ColorUIResource( rgb );
if( value.length() == 8 )
return new ColorUIResource( new Color( rgb, true ) );
if( reportError )
throw new NumberFormatException( value );
} catch( NumberFormatException ex ) {
if( reportError )
throw new IllegalArgumentException( "invalid color '" + value + "'" );
// not a color --> ignore
}
return null;
}
private static ColorUIResource parseColorFunctions( String value, boolean reportError ) {
int paramsStart = value.indexOf( '(' );
if( paramsStart < 0 ) {
if( reportError )
throw new IllegalArgumentException( "missing opening parenthesis in function '" + value + "'" );
return null;
}
String function = value.substring( 0, paramsStart ).trim();
List<String> params = split( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
if( params.isEmpty() )
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
switch( function ) {
case "lighten": return parseColorLightenOrDarken( true, params, reportError );
case "darken": return parseColorLightenOrDarken( false, params, reportError );
}
throw new IllegalArgumentException( "unknown color function '" + value + "'" );
}
/**
* Syntax: lighten(amount[,options]) or darken(amount[,options])
* - amount: percentage 0-100%
* - options: [relative] [autoInverse]
*/
private static ColorUIResource parseColorLightenOrDarken( boolean lighten, List<String> params, boolean reportError ) {
int amount = parsePercentage( params.get( 0 ) );
boolean relative = false;
boolean autoInverse = false;
if( params.size() >= 2 ) {
String options = params.get( 1 );
relative = options.contains( "relative" );
autoInverse = options.contains( "autoInverse" );
}
return new DerivedColor( lighten
? new ColorFunctions.Lighten( amount, relative, autoInverse )
: new ColorFunctions.Darken( amount, relative, autoInverse ) );
}
private static int parsePercentage( String value ) {
if( !value.endsWith( "%" ) )
throw new NumberFormatException( "invalid percentage '" + value + "'" );
int val;
try {
val = Integer.parseInt( value.substring( 0, value.length() - 1 ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid percentage '" + value + "'" );
}
if( val < 0 || val > 100 )
throw new IllegalArgumentException( "percentage out of range (0-100%) '" + value + "'" );
return val;
}
private static Integer parseInteger( String value, boolean reportError ) {
try {
return Integer.parseInt( value );
} catch( NumberFormatException ex ) {
if( reportError )
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
return null;
}
private static ScaledNumber parseScaledNumber( String value ) {
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
}
static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>();
int delimIndex = str.indexOf( delim );
int index = 0;
while( delimIndex >= 0 ) {
strs.add( str.substring( index, delimIndex ) );
index = delimIndex + 1;
delimIndex = str.indexOf( delim, index );
}
strs.add( str.substring( index ) );
return strs;
}
}

View File

@@ -16,14 +16,18 @@
package com.formdev.flatlaf.icons;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* Icon for {@link javax.swing.JCheckBox}.
@@ -50,6 +54,7 @@ import com.formdev.flatlaf.ui.FlatButtonUI;
* @uiDefault CheckBox.icon.selectedPressedBackground Color optional
* @uiDefault CheckBox.icon.checkmarkColor Color
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color
* @uiDefault CheckBox.arc int
*
* @author Karl Tauber
*/
@@ -58,6 +63,7 @@ public class FlatCheckBoxIcon
{
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
protected final Color borderColor = UIManager.getColor( "CheckBox.icon.borderColor" );
protected final Color disabledBorderColor = UIManager.getColor( "CheckBox.icon.disabledBorderColor" );
@@ -84,7 +90,8 @@ public class FlatCheckBoxIcon
@Override
protected void paintIcon( Component c, Graphics2D g2 ) {
boolean selected = (c instanceof AbstractButton) ? ((AbstractButton)c).isSelected() : false;
boolean indeterminate = c instanceof JComponent && clientPropertyEquals( (JComponent) c, SELECTED_STATE, SELECTED_STATE_INDETERMINATE );
boolean selected = indeterminate || (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
// paint focused border
if( c.hasFocus() && focusWidth > 0 ) {
@@ -102,33 +109,40 @@ public class FlatCheckBoxIcon
paintBorder( g2 );
// paint background
g2.setColor( FlatButtonUI.buttonStateColor( c,
FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
selected ? selectedBackground : background,
disabledBackground,
focusedBackground,
selected && selectedHoverBackground != null ? selectedHoverBackground : hoverBackground,
selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ) );
selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ),
background );
paintBackground( g2 );
// paint checkmark
if( selected ) {
if( selected || indeterminate ) {
g2.setColor( c.isEnabled() ? checkmarkColor : disabledCheckmarkColor );
paintCheckmark( g2 );
if( indeterminate )
paintIndeterminate( g2 );
else
paintCheckmark( g2 );
}
}
protected void paintFocusBorder( Graphics2D g2 ) {
// the outline focus border is painted outside of the icon
int wh = ICON_SIZE - 1 + (focusWidth * 2);
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, 8, 8 );
int arcwh = (arc + focusWidth) * 2;
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
}
protected void paintBorder( Graphics2D g2 ) {
g2.fillRoundRect( 1, 0, 14, 14, 4, 4 );
int arcwh = arc * 2;
g2.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
}
protected void paintBackground( Graphics2D g2 ) {
g2.fillRoundRect( 2, 1, 12, 12, 3, 3 );
int arcwh = (arc * 2) - 1;
g2.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
}
protected void paintCheckmark( Graphics2D g2 ) {
@@ -140,4 +154,8 @@ public class FlatCheckBoxIcon
g2.setStroke( new BasicStroke( 1.9f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
g2.draw( path );
}
protected void paintIndeterminate( Graphics2D g2 ) {
g2.fill( new RoundRectangle2D.Float( 3.75f, 5.75f, 8.5f, 2.5f, 2f, 2f ) );
}
}

View File

@@ -24,6 +24,7 @@ import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* Help button icon for {@link javax.swing.JButton}.
@@ -99,12 +100,12 @@ public class FlatHelpButtonIcon
g2.fill( new Ellipse2D.Float( focusWidth + 0.5f, focusWidth + 0.5f, 21, 21 ) );
// paint background
g2.setColor( FlatButtonUI.buttonStateColor( c,
FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
background,
disabledBackground,
focusedBackground,
hoverBackground,
pressedBackground ) );
pressedBackground ), background );
g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) );
// paint question mark

View File

@@ -23,7 +23,6 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Paint;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
@@ -83,7 +82,7 @@ public class FlatBorder
getLineWidth() + scale( (float) innerFocusWidth ), arc );
}
g2.setPaint( getBorderColor( c ) );
g2.setColor( getBorderColor( c ) );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, borderWidth, arc );
} finally {
g2.dispose();
@@ -94,7 +93,7 @@ public class FlatBorder
return focusColor;
}
protected Paint getBorderColor( Component c ) {
protected Color getBorderColor( Component c ) {
boolean enabled = c.isEnabled() && (!(c instanceof JTextComponent) || ((JTextComponent)c).isEditable());
return enabled
? (isFocused( c ) ? focusedBorderColor : borderColor)

View File

@@ -21,7 +21,6 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Paint;
import javax.swing.JButton;
import javax.swing.UIManager;
import javax.swing.plaf.UIResource;
@@ -68,7 +67,7 @@ public class FlatButtonBorder
}
@Override
protected Paint getBorderColor( Component c ) {
protected Color getBorderColor( Component c ) {
boolean def = FlatButtonUI.isDefaultButton( c );
return FlatButtonUI.buttonStateColor( c,
def ? defaultBorderColor : borderColor,

View File

@@ -131,6 +131,7 @@ public class FlatButtonUI
defaults_initialized = true;
}
LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
MigLayoutVisualPadding.install( b, focusWidth );
@@ -169,15 +170,16 @@ public class FlatButtonUI
@Override
public void update( Graphics g, JComponent c ) {
if( isHelpButton( c ) ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() )
FlatUIUtils.paintParentBackground( g, c );
if( isHelpButton( c ) ) {
helpButtonIcon.paintIcon( c, g, 0, 0 );
return;
}
if( c.isOpaque() && isContentAreaFilled( c ) ) {
FlatUIUtils.paintParentBackground( g, c );
if( isContentAreaFilled( c ) ) {
Color background = getBackground( c );
if( background != null ) {
Graphics2D g2 = (Graphics2D) g.create();
@@ -188,7 +190,7 @@ public class FlatButtonUI
float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (border instanceof FlatButtonBorder || isToolBarButton( c )) ? scale( (float) this.arc ) : 0;
g2.setColor( background );
FlatUIUtils.setColor( g2, background, isDefaultButton(c) ? defaultBackground : c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
@@ -40,6 +41,7 @@ import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
@@ -122,6 +124,8 @@ public class FlatComboBoxUI
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( comboBox, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
arrowType = UIManager.getString( "Component.arrowType" );
@@ -208,11 +212,14 @@ public class FlatComboBoxUI
String propertyName = e.getPropertyName();
if( editor != null &&
((source == comboBox && (propertyName == "background" || propertyName == "foreground")) ||
((source == comboBox && propertyName == "foreground") ||
(source == editor && propertyName == "enabled")) )
{
// fix editor component colors
updateEditorColors();
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
editor.applyComponentOrientation( o );
}
}
};
@@ -235,6 +242,12 @@ public class FlatComboBoxUI
if( editor instanceof JTextComponent )
((JTextComponent)editor).setBorder( BorderFactory.createEmptyBorder() );
// explicitly make non-opaque
if( editor instanceof JComponent )
((JComponent)editor).setOpaque( false );
editor.applyComponentOrientation( comboBox.getComponentOrientation() );
updateEditorColors();
}
@@ -243,7 +256,6 @@ public class FlatComboBoxUI
// is used, then the editor is updated after the combobox and the
// colors are again replaced with default colors
boolean enabled = editor.isEnabled();
editor.setBackground( FlatUIUtils.nonUIResource( enabled ? comboBox.getBackground() : disabledBackground ) );
editor.setForeground( FlatUIUtils.nonUIResource( (enabled || editor instanceof JTextComponent)
? comboBox.getForeground()
: disabledForeground ) );
@@ -265,44 +277,44 @@ public class FlatComboBoxUI
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
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 = arrowButton.getX();
int arrowWidth = arrowButton.getWidth();
boolean enabled = comboBox.isEnabled();
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
int arrowX = arrowButton.getX();
int arrowWidth = arrowButton.getWidth();
boolean enabled = comboBox.isEnabled();
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
// 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( comboBox.isEditable() ? buttonEditableBackground : 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 arrow button background
if( enabled ) {
g2.setColor( comboBox.isEditable() ? buttonEditableBackground : 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 );
}
if( comboBox.isEditable() ) {
// 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 vertical line between value and arrow button
if( comboBox.isEditable() ) {
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 );
@@ -315,6 +327,7 @@ public class FlatComboBoxUI
CellPaddingBorder.uninstall( renderer );
Component c = renderer.getListCellRendererComponent( listBox, comboBox.getSelectedItem(), -1, false, false );
c.setFont( comboBox.getFont() );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
CellPaddingBorder.uninstall( c );
boolean enabled = comboBox.isEnabled();
@@ -373,6 +386,15 @@ public class FlatComboBoxUI
FlatComboPopup( JComboBox combo ) {
super( combo );
// BasicComboPopup listens to JComboBox.componentOrientation and updates
// the component orientation of the list, scroller and popup, but when
// switching the LaF and a new combo popup is created, the component
// orientation is not applied.
ComponentOrientation o = comboBox.getComponentOrientation();
list.setComponentOrientation( o );
scroller.setComponentOrientation( o );
setComponentOrientation( o );
}
@Override
@@ -386,7 +408,13 @@ public class FlatComboBoxUI
comboBox.setPrototypeDisplayValue( prototype );
// make popup wider if necessary
pw = Math.max( pw, displaySize.width );
if( displaySize.width > pw ) {
int diff = displaySize.width - pw;
pw = displaySize.width;
if( !comboBox.getComponentOrientation().isLeftToRight() )
px -= diff;
}
return super.computePopupBounds( px, py, pw, ph );
}
@@ -433,6 +461,7 @@ public class FlatComboBoxUI
CellPaddingBorder.uninstall( renderer );
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
c.applyComponentOrientation( comboBox.getComponentOrientation() );
if( c instanceof JComponent ) {
if( paddingBorder == null )

View File

@@ -19,15 +19,12 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -46,7 +43,7 @@ public class FlatPasswordFieldUI
protected int focusWidth;
protected int minimumWidth;
private Handler handler;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatPasswordFieldUI();
@@ -63,6 +60,8 @@ public class FlatPasswordFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth );
}
@@ -77,41 +76,27 @@ public class FlatPasswordFieldUI
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener( getHandler() );
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( getHandler() );
handler = null;
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
public Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@Override
protected void paintSafely( Graphics g ) {
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth );
super.paintSafely( g );
}
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
g2.setColor( c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, 0 );
} finally {
g2.dispose();
}
// background is painted elsewhere
}
@Override
@@ -129,20 +114,4 @@ public class FlatPasswordFieldUI
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size;
}
//---- class Handler ------------------------------------------------------
private class Handler
implements FocusListener
{
@Override
public void focusGained( FocusEvent e ) {
getComponent().repaint();
}
@Override
public void focusLost( FocusEvent e ) {
getComponent().repaint();
}
}
}

View File

@@ -23,6 +23,7 @@ import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI;
import com.formdev.flatlaf.util.UIScale;
@@ -39,6 +40,13 @@ public class FlatProgressBarUI
return new FlatProgressBarUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( progressBar, "opaque", false );
}
@Override
protected Dimension getPreferredInnerHorizontal() {
return UIScale.scale( super.getPreferredInnerHorizontal() );

View File

@@ -66,6 +66,7 @@ public class FlatRadioButtonUI
defaults_initialized = true;
}
LookAndFeel.installProperty( b, "opaque", false );
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
MigLayoutVisualPadding.install( b, null );

View File

@@ -17,10 +17,8 @@
package com.formdev.flatlaf.ui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
@@ -29,10 +27,9 @@ import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.ScrollPaneLayout;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicScrollPaneUI;
/**
@@ -53,17 +50,14 @@ public class FlatScrollPaneUI
public void installUI( JComponent c ) {
super.installUI( c );
if( scrollpane.getLayout() instanceof UIResource )
scrollpane.setLayout( new FlatScrollPaneLayout() );
int focusWidth = UIManager.getInt( "Component.focusWidth" );
LookAndFeel.installProperty( c, "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( scrollpane, UIManager.getInt( "Component.focusWidth" ) );
MigLayoutVisualPadding.install( scrollpane, focusWidth );
}
@Override
public void uninstallUI( JComponent c ) {
if( scrollpane.getLayout() instanceof FlatScrollPaneLayout )
scrollpane.setLayout( new ScrollPaneLayout.UIResource() );
MigLayoutVisualPadding.uninstall( scrollpane );
super.uninstallUI( c );
@@ -169,27 +163,4 @@ public class FlatScrollPaneUI
scrollpane.repaint();
}
}
//---- class FlatScrollPaneLayout -----------------------------------------
private static class FlatScrollPaneLayout
extends ScrollPaneLayout
{
@Override
public void layoutContainer( Container parent ) {
super.layoutContainer( parent );
// increase height of vertical scroll bar so that it also fills the upper right corner
if( colHead != null && vsb != null && colHead.isVisible() && vsb.isVisible() ) {
Rectangle colHeadBounds = colHead.getBounds();
Rectangle vsbBounds = vsb.getBounds();
if( vsbBounds.y > colHeadBounds.y ) {
vsbBounds.height += (vsbBounds.y - colHeadBounds.y);
vsbBounds.y = colHeadBounds.y;
vsb.setBounds( vsbBounds );
}
}
}
}
}

View File

@@ -25,6 +25,7 @@ import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JSlider;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSliderUI;
@@ -96,6 +97,8 @@ public class FlatSliderUI
protected void installDefaults( JSlider slider ) {
super.installDefaults( slider );
LookAndFeel.installProperty( slider, "opaque", false );
trackWidth = UIManager.getInt( "Slider.trackWidth" );
thumbWidth = UIManager.getInt( "Slider.thumbWidth" );
@@ -170,9 +173,15 @@ public class FlatSliderUI
if( slider.getOrientation() == JSlider.HORIZONTAL ) {
float y = trackRect.y + (trackRect.height - tw) / 2f;
if( enabled && isRoundThumb() ) {
int cw = thumbRect.x + (thumbRect.width / 2) - trackRect.x;
coloredTrack = new RoundRectangle2D.Float( trackRect.x, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x + cw, y, trackRect.width - cw, tw, arc, arc );
if( slider.getComponentOrientation().isLeftToRight() ) {
int cw = thumbRect.x + (thumbRect.width / 2) - trackRect.x;
coloredTrack = new RoundRectangle2D.Float( trackRect.x, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x + cw, y, trackRect.width - cw, tw, arc, arc );
} else {
int cw = trackRect.x + trackRect.width - thumbRect.x - (thumbRect.width / 2);
coloredTrack = new RoundRectangle2D.Float( trackRect.x + trackRect.width - cw, y, cw, tw, arc, arc );
track = new RoundRectangle2D.Float( trackRect.x, y, trackRect.width - cw, tw, arc, arc );
}
} else
track = new RoundRectangle2D.Float( trackRect.x, y, trackRect.width, tw, arc, arc );
} else {

View File

@@ -35,6 +35,7 @@ import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
@@ -88,6 +89,8 @@ public class FlatSpinnerUI
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( spinner, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
@@ -152,6 +155,13 @@ public class FlatSpinnerUI
@Override
protected JComponent createEditor() {
JComponent editor = super.createEditor();
// explicitly make non-opaque
editor.setOpaque( false );
JTextField textField = getEditorTextField( editor );
if( textField != null )
textField.setOpaque( false );
updateEditorColors();
return editor;
}
@@ -183,8 +193,6 @@ public class FlatSpinnerUI
// use non-UIResource colors because when SwingUtilities.updateComponentTreeUI()
// is used, then the text field is updated after the spinner and the
// colors are again replaced with default colors
textField.setBackground( FlatUIUtils.nonUIResource( spinner.isEnabled()
? spinner.getBackground() : disabledBackground ) );
textField.setForeground( FlatUIUtils.nonUIResource( spinner.getForeground() ) );
textField.setDisabledTextColor( FlatUIUtils.nonUIResource( disabledForeground ) );
}
@@ -225,45 +233,45 @@ public class FlatSpinnerUI
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && (focusWidth > 0 || arc != 0) )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
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;
Component nextButton = getHandler().nextButton;
int arrowX = nextButton.getX();
int arrowWidth = nextButton.getWidth();
boolean enabled = spinner.isEnabled();
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
int width = c.getWidth();
int height = c.getHeight();
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (c.getBorder() instanceof FlatRoundBorder) ? scale( (float) this.arc ) : 0;
Component nextButton = getHandler().nextButton;
int arrowX = nextButton.getX();
int arrowWidth = nextButton.getWidth();
boolean enabled = spinner.isEnabled();
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow buttons 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 );
// paint arrow buttons 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 buttons
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) ) );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow buttons
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 );
}
@@ -370,7 +378,6 @@ public class FlatSpinnerUI
@Override
public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case "background":
case "foreground":
case "enabled":
updateEditorColors();

View File

@@ -21,11 +21,11 @@ import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JSpinner;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextFieldUI;
@@ -47,7 +47,7 @@ public class FlatTextFieldUI
protected int focusWidth;
protected int minimumWidth;
private Handler handler;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatTextFieldUI();
@@ -60,6 +60,8 @@ public class FlatTextFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth );
}
@@ -74,38 +76,51 @@ public class FlatTextFieldUI
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener( getHandler() );
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( getHandler() );
handler = null;
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
public Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@Override
protected void paintSafely( Graphics g ) {
paintBackground( g, getComponent(), focusWidth );
super.paintSafely( g );
}
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
// background is painted elsewhere
}
FlatUIUtils.paintParentBackground( g, c );
static void paintBackground( Graphics g, JTextComponent c, int focusWidth ) {
// do not paint background if:
// - not opaque and
// - border is not a flat border and
// - opaque was explicitly set (to false)
// (same behaviour as in AquaTextFieldUI)
if( !c.isOpaque() && !(c.getBorder() instanceof FlatBorder) && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
return;
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() && focusWidth > 0 )
FlatUIUtils.paintParentBackground( g, c );
// paint background
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float fFocusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) focusWidth ) : 0;
g2.setColor( c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, 0 );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
} finally {
g2.dispose();
}
@@ -132,20 +147,4 @@ public class FlatTextFieldUI
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size;
}
//---- class Handler ------------------------------------------------------
private class Handler
implements FocusListener
{
@Override
public void focusGained( FocusEvent e ) {
getComponent().repaint();
}
@Override
public void focusLost( FocusEvent e ) {
getComponent().repaint();
}
}
}

View File

@@ -74,11 +74,14 @@ public class FlatToolTipUI
List<String> lines = FlatLaf.split( ((JToolTip)c).getTipText(), '\n' );
int x = insets.left;
int x2 = c.getWidth() - insets.right;
int y = insets.top - fm.getDescent();
int lineHeight = fm.getHeight();
JComponent comp = ((JToolTip)c).getComponent();
boolean leftToRight = (comp != null ? comp : c).getComponentOrientation().isLeftToRight();
for( String line : lines ) {
y += lineHeight;
g.drawString( line, x, y );
g.drawString( line, leftToRight ? x : x2 - SwingUtilities.computeStringWidth( fm, line ), y );
}
} else
super.paint( g, c );

View File

@@ -26,6 +26,8 @@ import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
@@ -33,8 +35,10 @@ import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.function.Consumer;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.UIScale;
@@ -101,6 +105,12 @@ public class FlatUIUtils
MAC_USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE );
}
public static void setColor( Graphics g, Color color, Color baseColor ) {
if( color instanceof DerivedColor )
color = ((DerivedColor)color).derive( baseColor );
g.setColor( color );
}
/**
* Draws a round rectangle.
*/
@@ -246,15 +256,23 @@ public class FlatUIUtils
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
}
public static boolean hasOpaqueBeenExplicitlySet( JComponent c ) {
boolean oldOpaque = c.isOpaque();
LookAndFeel.installProperty( c, "opaque", !oldOpaque );
boolean explicitlySet = c.isOpaque() == oldOpaque;
LookAndFeel.installProperty( c, "opaque", oldOpaque );
return explicitlySet;
}
//---- class HoverListener ------------------------------------------------
public static class HoverListener
extends MouseAdapter
{
private final JComponent repaintComponent;
private final Component repaintComponent;
private final Consumer<Boolean> hoverChanged;
public HoverListener( JComponent repaintComponent, Consumer<Boolean> hoverChanged ) {
public HoverListener( Component repaintComponent, Consumer<Boolean> hoverChanged ) {
this.repaintComponent = repaintComponent;
this.hoverChanged = hoverChanged;
}
@@ -276,4 +294,26 @@ public class FlatUIUtils
repaintComponent.repaint();
}
}
//---- class RepaintFocusListener -----------------------------------------
public static class RepaintFocusListener
implements FocusListener
{
private final Component repaintComponent;
public RepaintFocusListener( Component repaintComponent ) {
this.repaintComponent = repaintComponent;
}
@Override
public void focusGained( FocusEvent e ) {
repaintComponent.repaint();
}
@Override
public void focusLost( FocusEvent e ) {
repaintComponent.repaint();
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* 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.util;
import java.awt.Color;
/**
* Functions that modify colors.
*
* @author Karl Tauber
*/
public class ColorFunctions
{
public static Color applyFunctions( Color color, ColorFunction[] functions ) {
float[] hsl = HSLColor.fromRGB( color );
float alpha = color.getAlpha() / 255f;
for( ColorFunction function : functions )
function.apply( hsl );
return HSLColor.toRGB( hsl, alpha );
}
private static float clamp( float value ) {
return (value < 0)
? 0
: ((value > 100)
? 100
: value);
}
//---- interface ColorFunction --------------------------------------------
public interface ColorFunction {
void apply( float[] hsl );
}
//---- class Lighten ------------------------------------------------------
/**
* Increase the lightness of a color in the HSL color space by an absolute
* or relative amount.
*/
public static class Lighten
implements ColorFunction
{
private final float amount;
private final boolean relative;
private final boolean autoInverse;
public Lighten( float amount, boolean relative, boolean autoInverse ) {
this.amount = amount;
this.relative = relative;
this.autoInverse = autoInverse;
}
@Override
public void apply( float[] hsl ) {
float amount2 = autoInverse && shouldInverse( hsl ) ? -amount : amount;
hsl[2] = clamp( relative
? (hsl[2] * ((100 + amount2) / 100))
: (hsl[2] + amount2) );
}
protected boolean shouldInverse( float[] hsl ) {
return hsl[2] >= 50;
}
}
//---- class Darken -------------------------------------------------------
/**
* Decrease the lightness of a color in the HSL color space by an absolute
* or relative amount.
*/
public static class Darken
extends Lighten
{
public Darken( float amount, boolean relative, boolean autoInverse ) {
super( -amount, relative, autoInverse );
}
@Override
protected boolean shouldInverse( float[] hsl ) {
return hsl[2] < 50;
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.util;
import java.awt.Color;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
/**
* A (red) color that acts as a placeholder in UI defaults.
* The actual color is derived from another color,
* which is modified by the given color functions.
*
* @author Karl Tauber
*/
public class DerivedColor
extends ColorUIResource
{
private final ColorFunction[] functions;
public DerivedColor( ColorFunction... functions ) {
super( Color.red );
this.functions = functions;
}
public Color derive( Color baseColor ) {
return ColorFunctions.applyFunctions( baseColor, functions );
}
}

View File

@@ -0,0 +1,432 @@
/*
* From http://tips4java.wordpress.com/2009/07/05/hsl-color/
*
* License note on http://tips4java.wordpress.com/about/
* "You are free to use and/or modify any or all code posted on the
* Java Tips Weblog without restriction. A credit in the code comments
* would be nice, but not in any way mandatory."
*/
package com.formdev.flatlaf.util;
import java.awt.Color;
/**
* The HSLColor class provides methods to manipulate HSL (Hue, Saturation
* Luminance) values to create a corresponding Color object using the RGB
* ColorSpace.
*
* The HUE is the color, the Saturation is the purity of the color (with
* respect to grey) and Luminance is the brightness of the color (with respect
* to black and white)
*
* The Hue is specified as an angel between 0 - 360 degrees where red is 0,
* green is 120 and blue is 240. In between you have the colors of the rainbow.
* Saturation is specified as a percentage between 0 - 100 where 100 is fully
* saturated and 0 approaches gray. Luminance is specified as a percentage
* between 0 - 100 where 0 is black and 100 is white.
*
* In particular the HSL color space makes it easier change the Tone or Shade
* of a color by adjusting the luminance value.
*/
public class HSLColor
{
private final Color rgb;
private final float[] hsl;
private final float alpha;
/**
* Create a HSLColor object using an RGB Color object.
*
* @param rgb the RGB Color object
*/
public HSLColor(Color rgb)
{
this.rgb = rgb;
hsl = fromRGB( rgb );
alpha = rgb.getAlpha() / 255.0f;
}
/**
* Create a HSLColor object using individual HSL values and a default
* alpha value of 1.0.
*
* @param h is the Hue value in degrees between 0 - 360
* @param s is the Saturation percentage between 0 - 100
* @param l is the Lumanance percentage between 0 - 100
*/
public HSLColor(float h, float s, float l)
{
this(h, s, l, 1.0f);
}
/**
* Create a HSLColor object using individual HSL values.
*
* @param h the Hue value in degrees between 0 - 360
* @param s the Saturation percentage between 0 - 100
* @param l the Lumanance percentage between 0 - 100
* @param alpha the alpha value between 0 - 1
*/
public HSLColor(float h, float s, float l, float alpha)
{
hsl = new float[] {h, s, l};
this.alpha = alpha;
rgb = toRGB(hsl, alpha);
}
/**
* Create a HSLColor object using an an array containing the
* individual HSL values and with a default alpha value of 1.
*
* @param hsl array containing HSL values
*/
public HSLColor(float[] hsl)
{
this(hsl, 1.0f);
}
/**
* Create a HSLColor object using an an array containing the
* individual HSL values.
*
* @param hsl array containing HSL values
* @param alpha the alpha value between 0 - 1
*/
public HSLColor(float[] hsl, float alpha)
{
this.hsl = hsl;
this.alpha = alpha;
rgb = toRGB(hsl, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Hue value. The degrees specified is an absolute value.
*
* @param degrees - the Hue value between 0 - 360
* @return the RGB Color object
*/
public Color adjustHue(float degrees)
{
return toRGB(degrees, hsl[1], hsl[2], alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Luminance value. The percent specified is an absolute value.
*
* @param percent - the Luminance value between 0 - 100
* @return the RGB Color object
*/
public Color adjustLuminance(float percent)
{
return toRGB(hsl[0], hsl[1], percent, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Saturation value. The percent specified is an absolute value.
*
* @param percent - the Saturation value between 0 - 100
* @return the RGB Color object
*/
public Color adjustSaturation(float percent)
{
return toRGB(hsl[0], percent, hsl[2], alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Shade. Changing the shade will return a darker color. The percent
* specified is a relative value.
*
* @param percent - the value between 0 - 100
* @return the RGB Color object
*/
public Color adjustShade(float percent)
{
float multiplier = (100.0f - percent) / 100.0f;
float l = Math.max(0.0f, hsl[2] * multiplier);
return toRGB(hsl[0], hsl[1], l, alpha);
}
/**
* Create a RGB Color object based on this HSLColor with a different
* Tone. Changing the tone will return a lighter color. The percent
* specified is a relative value.
*
* @param percent - the value between 0 - 100
* @return the RGB Color object
*/
public Color adjustTone(float percent)
{
float multiplier = (100.0f + percent) / 100.0f;
float l = Math.min(100.0f, hsl[2] * multiplier);
return toRGB(hsl[0], hsl[1], l, alpha);
}
/**
* Get the Alpha value.
*
* @return the Alpha value.
*/
public float getAlpha()
{
return alpha;
}
/**
* Create a RGB Color object that is the complementary color of this
* HSLColor. This is a convenience method. The complementary color is
* determined by adding 180 degrees to the Hue value.
* @return the RGB Color object
*/
public Color getComplementary()
{
float hue = (hsl[0] + 180.0f) % 360.0f;
return toRGB(hue, hsl[1], hsl[2]);
}
/**
* Get the Hue value.
*
* @return the Hue value.
*/
public float getHue()
{
return hsl[0];
}
/**
* Get the HSL values.
*
* @return the HSL values.
*/
public float[] getHSL()
{
return hsl;
}
/**
* Get the Luminance value.
*
* @return the Luminance value.
*/
public float getLuminance()
{
return hsl[2];
}
/**
* Get the RGB Color object represented by this HDLColor.
*
* @return the RGB Color object.
*/
public Color getRGB()
{
return rgb;
}
/**
* Get the Saturation value.
*
* @return the Saturation value.
*/
public float getSaturation()
{
return hsl[1];
}
@Override
public String toString()
{
String toString =
"HSLColor[h=" + hsl[0] +
",s=" + hsl[1] +
",l=" + hsl[2] +
",alpha=" + alpha + "]";
return toString;
}
/**
* Convert a RGB Color to it corresponding HSL values.
*
* @return an array containing the 3 HSL values.
*/
public static float[] fromRGB(Color color)
{
// Get RGB values in the range 0 - 1
float[] rgb = color.getRGBColorComponents( null );
float r = rgb[0];
float g = rgb[1];
float b = rgb[2];
// Minimum and Maximum RGB values are used in the HSL calculations
float min = Math.min(r, Math.min(g, b));
float max = Math.max(r, Math.max(g, b));
// Calculate the Hue
float h = 0;
if (max == min)
h = 0;
else if (max == r)
h = ((60 * (g - b) / (max - min)) + 360) % 360;
else if (max == g)
h = (60 * (b - r) / (max - min)) + 120;
else if (max == b)
h = (60 * (r - g) / (max - min)) + 240;
// Calculate the Luminance
float l = (max + min) / 2;
// System.out.println(max + " : " + min + " : " + l);
// Calculate the Saturation
float s = 0;
if (max == min)
s = 0;
else if (l <= .5f)
s = (max - min) / (max + min);
else
s = (max - min) / (2 - max - min);
// System.out.println(new HSLColor( new float[] {h, s * 100, l * 100} ));
return new float[] {h, s * 100, l * 100};
}
/**
* Convert HSL values to a RGB Color with a default alpha value of 1.
* H (Hue) is specified as degrees in the range 0 - 360.
* S (Saturation) is specified as a percentage in the range 1 - 100.
* L (Lumanance) is specified as a percentage in the range 1 - 100.
*
* @param hsl an array containing the 3 HSL values
*
* @returns the RGB Color object
*/
public static Color toRGB(float[] hsl)
{
return toRGB(hsl, 1.0f);
}
/**
* Convert HSL values to a RGB Color.
* H (Hue) is specified as degrees in the range 0 - 360.
* S (Saturation) is specified as a percentage in the range 1 - 100.
* L (Lumanance) is specified as a percentage in the range 1 - 100.
*
* @param hsl an array containing the 3 HSL values
* @param alpha the alpha value between 0 - 1
*
* @returns the RGB Color object
*/
public static Color toRGB(float[] hsl, float alpha)
{
return toRGB(hsl[0], hsl[1], hsl[2], alpha);
}
/**
* Convert HSL values to a RGB Color with a default alpha value of 1.
*
* @param h Hue is specified as degrees in the range 0 - 360.
* @param s Saturation is specified as a percentage in the range 1 - 100.
* @param l Lumanance is specified as a percentage in the range 1 - 100.
*
* @returns the RGB Color object
*/
public static Color toRGB(float h, float s, float l)
{
return toRGB(h, s, l, 1.0f);
}
/**
* Convert HSL values to a RGB Color.
*
* @param h Hue is specified as degrees in the range 0 - 360.
* @param s Saturation is specified as a percentage in the range 1 - 100.
* @param l Lumanance is specified as a percentage in the range 1 - 100.
* @param alpha the alpha value between 0 - 1
*
* @returns the RGB Color object
*/
public static Color toRGB(float h, float s, float l, float alpha)
{
if (s <0.0f || s > 100.0f)
{
String message = "Color parameter outside of expected range - Saturation";
throw new IllegalArgumentException( message );
}
if (l <0.0f || l > 100.0f)
{
String message = "Color parameter outside of expected range - Luminance";
throw new IllegalArgumentException( message );
}
if (alpha <0.0f || alpha > 1.0f)
{
String message = "Color parameter outside of expected range - Alpha";
throw new IllegalArgumentException( message );
}
// Formula needs all values between 0 - 1.
h = h % 360.0f;
h /= 360f;
s /= 100f;
l /= 100f;
float q = 0;
if (l < 0.5)
q = l * (1 + s);
else
q = (l + s) - (s * l);
float p = 2 * l - q;
float r = Math.max(0, HueToRGB(p, q, h + (1.0f / 3.0f)));
float g = Math.max(0, HueToRGB(p, q, h));
float b = Math.max(0, HueToRGB(p, q, h - (1.0f / 3.0f)));
r = Math.min(r, 1.0f);
g = Math.min(g, 1.0f);
b = Math.min(b, 1.0f);
return new Color(r, g, b, alpha);
}
private static float HueToRGB(float p, float q, float h)
{
if (h < 0) h += 1;
if (h > 1 ) h -= 1;
if (6 * h < 1)
{
return p + ((q - p) * 6 * h);
}
if (2 * h < 1 )
{
return q;
}
if (3 * h < 2)
{
return p + ( (q - p) * 6 * ((2.0f / 3.0f) - h) );
}
return p;
}
}

View File

@@ -24,4 +24,6 @@ module com.formdev.flatlaf {
exports com.formdev.flatlaf.icons;
exports com.formdev.flatlaf.ui;
exports com.formdev.flatlaf.util;
uses com.formdev.flatlaf.FlatDefaultsAddon;
}

View File

@@ -31,6 +31,10 @@
@cellFocusColor=000000
@icon=adadad
# Button
@buttonHoverBackground=lighten(3%,autoInverse)
@buttonPressedBackground=lighten(6%,autoInverse)
#---- globals ----
@@ -63,8 +67,8 @@ window=@background
#---- Button ----
Button.background=4c5052
Button.hoverBackground=525658
Button.pressedBackground=5c6164
Button.hoverBackground=@buttonHoverBackground
Button.pressedBackground=@buttonPressedBackground
Button.borderColor=5e6060
Button.disabledBorderColor=5e6060
@@ -73,8 +77,8 @@ Button.hoverBorderColor=@@Button.focusedBorderColor
Button.default.background=365880
Button.default.foreground=bbbbbb
Button.default.hoverBackground=3d6185
Button.default.pressedBackground=43688c
Button.default.hoverBackground=@buttonHoverBackground
Button.default.pressedBackground=@buttonPressedBackground
Button.default.borderColor=4c708c
Button.default.hoverBorderColor=537699
Button.default.focusedBorderColor=537699
@@ -95,8 +99,8 @@ CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
CheckBox.icon.selectedFocusedBorderColor=466D94
CheckBox.icon.background=43494A
CheckBox.icon.disabledBackground=@background
CheckBox.icon.hoverBackground=4c5052
CheckBox.icon.pressedBackground=@@Button.pressedBackground
CheckBox.icon.hoverBackground=@buttonHoverBackground
CheckBox.icon.pressedBackground=@buttonPressedBackground
CheckBox.icon.selectedBackground=43494A
CheckBox.icon.checkmarkColor=A7A7A7
CheckBox.icon.disabledCheckmarkColor=606060

View File

@@ -77,6 +77,7 @@ Button.default.borderWidth=1
CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon
CheckBox.arc=2
CheckBox.margin=2,2,2,2
CheckBox.iconTextGap=4
CheckBox.rollover=true
@@ -277,6 +278,7 @@ ScrollBar.width=10
ScrollPane.border=com.formdev.flatlaf.ui.FlatBorder
ScrollPane.background=@@ScrollBar.track
ScrollPane.fillUpperCorner=true
#---- Separator ----
@@ -409,6 +411,7 @@ ToolBar.separatorColor=@@Separator.foreground
#---- ToolTip ----
ToolTip.border=4,6,4,6,@@Component.borderColor
ToolTip.borderInactive=null
ToolTip.backgroundInactive=@@ToolTip.background
ToolTip.foregroundInactive=@disabledText

View File

@@ -31,6 +31,10 @@
@cellFocusColor=000000
@icon=afafaf
# Button
@buttonHoverBackground=darken(3%,autoInverse)
@buttonPressedBackground=darken(10%,autoInverse)
#---- globals ----
@@ -64,8 +68,8 @@ window=@background
Button.background=ffffff
Button.focusedBackground=e3f1fa
Button.hoverBackground=f8f8f8
Button.pressedBackground=dfdfdf
Button.hoverBackground=@buttonHoverBackground
Button.pressedBackground=@buttonPressedBackground
Button.borderColor=bfbfbf
Button.disabledBorderColor=cfcfcf
@@ -75,8 +79,8 @@ Button.hoverBorderColor=@@Button.focusedBorderColor
Button.default.background=@@Button.background
Button.default.foreground=@foreground
Button.default.focusedBackground=@@Button.focusedBackground
Button.default.hoverBackground=@@Button.hoverBackground
Button.default.pressedBackground=@@Button.pressedBackground
Button.default.hoverBackground=@buttonHoverBackground
Button.default.pressedBackground=@buttonPressedBackground
Button.default.borderColor=4D89C9
Button.default.hoverBorderColor=@@Button.hoverBorderColor
Button.default.focusedBorderColor=@@Button.focusedBorderColor
@@ -97,8 +101,8 @@ CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
CheckBox.icon.background=FFFFFF
CheckBox.icon.disabledBackground=@background
CheckBox.icon.focusedBackground=@@Button.focusedBackground
CheckBox.icon.hoverBackground=@@Button.hoverBackground
CheckBox.icon.pressedBackground=@@Button.pressedBackground
CheckBox.icon.hoverBackground=@buttonHoverBackground
CheckBox.icon.pressedBackground=@buttonPressedBackground
CheckBox.icon.selectedBackground=FFFFFF
CheckBox.icon.checkmarkColor=4D89C9
CheckBox.icon.disabledCheckmarkColor=ABABAB
@@ -234,7 +238,6 @@ ToggleButton.toolbar.selectedBackground=cfcfcf
#---- ToolTip ----
ToolTip.border=4,6,4,6,@@Component.borderColor
ToolTip.background=fafafa

View File

@@ -205,18 +205,37 @@ class DemoFrame
//======== toolBar1 ========
{
toolBar1.setMargin(new Insets(3, 3, 3, 3));
//---- backButton ----
backButton.setToolTipText("Back");
toolBar1.add(backButton);
//---- forwardButton ----
forwardButton.setToolTipText("Forward");
toolBar1.add(forwardButton);
toolBar1.addSeparator();
//---- cutButton ----
cutButton.setToolTipText("Cut");
toolBar1.add(cutButton);
//---- copyButton ----
copyButton.setToolTipText("Copy");
toolBar1.add(copyButton);
//---- pasteButton ----
pasteButton.setToolTipText("Paste");
toolBar1.add(pasteButton);
toolBar1.addSeparator();
//---- refreshButton ----
refreshButton.setToolTipText("Refresh");
toolBar1.add(refreshButton);
toolBar1.addSeparator();
//---- showToggleButton ----
showToggleButton.setSelected(true);
showToggleButton.setToolTipText("Show Details");
toolBar1.add(showToggleButton);
}
contentPane.add(toolBar1, BorderLayout.NORTH);

View File

@@ -17,27 +17,33 @@ new FormModel {
"margin": new java.awt.Insets( 3, 3, 3, 3 )
add( new FormComponent( "javax.swing.JButton" ) {
name: "backButton"
"toolTipText": "Back"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "forwardButton"
"toolTipText": "Forward"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator5"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "cutButton"
"toolTipText": "Cut"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "copyButton"
"toolTipText": "Copy"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "pasteButton"
"toolTipText": "Paste"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator6"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "refreshButton"
"toolTipText": "Refresh"
} )
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
name: "separator7"
@@ -45,6 +51,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JToggleButton" ) {
name: "showToggleButton"
"selected": true
"toolTipText": "Show Details"
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "North"

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.demo;
import java.util.prefs.Preferences;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLightLaf;
@@ -32,29 +33,31 @@ public class FlatLafDemo
static Preferences prefs;
public static void main( String[] args ) {
prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
SwingUtilities.invokeLater( () -> {
prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
// set look and feel
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else {
String lafClassName = prefs.get( KEY_LAF, FlatLightLaf.class.getName() );
UIManager.setLookAndFeel( lafClassName );
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
} catch( Exception ex ) {
ex.printStackTrace();
// fallback
FlatLightLaf.install();
}
// create frame
DemoFrame frame = new DemoFrame();
// create frame
DemoFrame frame = new DemoFrame();
// show frame
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
// show frame
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
} );
}
}

13
flatlaf-extras/README.md Normal file
View File

@@ -0,0 +1,13 @@
FlatLaf Extras
==============
This sub-project provides some additional components and classes:
- [TriStateCheckBox](src/main/java/com/formdev/flatlaf/extras/TriStateCheckBox.java):
A tri-state check box.
Download
--------
Not yet available.

View File

@@ -0,0 +1,30 @@
/*
* 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`
}
dependencies {
implementation( project( ":flatlaf-core" ) )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@@ -0,0 +1,107 @@
/*
* 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.extras;
import java.awt.event.ItemEvent;
import javax.swing.JCheckBox;
/**
* A tri-state check box.
*
* To display the third state, this component requires an LaF that supports painting
* the indeterminate state if client property {@code "JButton.selectedState"} has the
* value {@code "indeterminate"}.
*
* FlatLaf and Mac Aqua LaF support the third state.
*
* @author Karl Tauber
*/
public class TriStateCheckBox
extends JCheckBox
{
public enum State { INDETERMINATE, SELECTED, UNSELECTED }
private State state;
private boolean thirdStateEnabled = true;
public TriStateCheckBox() {
this( null );
}
public TriStateCheckBox( String text ) {
this( text, State.INDETERMINATE );
}
public TriStateCheckBox( String text, State initialState ) {
super( text );
setModel( new ToggleButtonModel() {
@Override
public boolean isSelected() {
return state != State.UNSELECTED;
}
@Override
public void setSelected( boolean b ) {
switch( state ) {
case INDETERMINATE: setState( State.SELECTED ); break;
case SELECTED: setState( State.UNSELECTED ); break;
case UNSELECTED: setState( thirdStateEnabled ? State.INDETERMINATE : State.SELECTED ); break;
}
fireStateChanged();
fireItemStateChanged( new ItemEvent( this, ItemEvent.ITEM_STATE_CHANGED, this,
isSelected() ? ItemEvent.SELECTED : ItemEvent.DESELECTED ) );
}
} );
setState( initialState );
}
public State getState() {
return state;
}
public void setState( State state ) {
if( this.state == state )
return;
State oldState = this.state;
this.state = state;
putClientProperty( "JButton.selectedState", state == State.INDETERMINATE ? "indeterminate" : null );
firePropertyChange( "state", oldState, state );
repaint();
}
public boolean isThirdStateEnabled() {
return thirdStateEnabled;
}
public void setThirdStateEnabled( boolean thirdStateEnabled ) {
this.thirdStateEnabled = thirdStateEnabled;
if( state == State.INDETERMINATE )
setState( State.UNSELECTED );
}
@Override
public void setSelected( boolean b ) {
setState( b ? State.SELECTED : State.UNSELECTED );
}
}

View File

@@ -32,7 +32,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf-swingx
version: 0.15
version: 0.17
Otherwise download `flatlaf-swingx-<version>.jar` here:

View File

@@ -25,10 +25,6 @@ plugins {
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 {
@@ -37,6 +33,12 @@ java {
}
tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
javadoc {
options {

View File

@@ -28,8 +28,6 @@ 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;
@@ -105,6 +103,8 @@ public class FlatDatePickerUI
super.installUI( c );
LookAndFeel.installProperty( datePicker, "opaque", false );
// hack JXDatePicker.TodayPanel colors
// (there is no need to uninstall these changes because only UIResources are used,
// which are automatically replaced when switching LaF)
@@ -159,18 +159,7 @@ public class FlatDatePickerUI
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();
}
} );
editor.addFocusListener( new FlatUIUtils.RepaintFocusListener( datePicker ) );
return editor;
}
@@ -230,44 +219,44 @@ public class FlatDatePickerUI
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
// fill background if opaque to avoid garbage if user sets opaque to true
if( c.isOpaque() )
FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g;
FlatUIUtils.setRenderingHints( g2 );
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();
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 );
// 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 );
// 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) ) );
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 );
}

View File

@@ -0,0 +1,37 @@
/*
* 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`
}
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( project( ":flatlaf-extras" ) )
implementation( project( ":flatlaf-swingx" ) )
implementation( "com.miglayout:miglayout-swing:5.2" )
implementation( "com.jgoodies:jgoodies-forms:1.9.0" )
implementation( "org.swinglabs.swingx:swingx-all:1.6.5-1" )
implementation( "org.swinglabs.swingx:swingx-beaninfo:1.6.5-1" )
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import javax.swing.*;
import net.miginfocom.swing.*;
@@ -23,11 +23,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatChooserTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
frame.showFrame( new FlatChooserTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
frame.showFrame( FlatChooserTest::new );
} );
}
FlatChooserTest() {
@@ -54,7 +56,7 @@ public class FlatChooserTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]",

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][]"
"$rowConstraints": "[top][top][]"
} ) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import javax.swing.*;
import javax.swing.table.*;
@@ -24,11 +24,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatComponents2Test
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponents2Test" );
frame.showFrame( new FlatComponents2Test() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponents2Test" );
frame.showFrame( FlatComponents2Test::new );
} );
}
FlatComponents2Test() {
@@ -60,7 +62,7 @@ public class FlatComponents2Test
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[200]" +

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][200][200]"
"$rowConstraints": "[][][][::200][::150]"
} ) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import javax.swing.*;
@@ -25,11 +25,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatComponentsTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" );
frame.showFrame( new FlatComponentsTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" );
frame.showFrame( FlatComponentsTest::new );
} );
}
FlatComponentsTest() {
@@ -176,7 +178,7 @@ public class FlatComponentsTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]" +
@@ -243,6 +245,7 @@ public class FlatComponentsTest
//---- button5 ----
button5.setText("default");
button5.setDisplayedMnemonicIndex(0);
button5.setToolTipText("Tool tip with\nmultiple\nlines.");
add(button5, "cell 3 1");
//---- button3 ----
@@ -346,7 +349,15 @@ public class FlatComponentsTest
"editable",
"a",
"bb",
"ccc"
"ccc",
"dd",
"e",
"ff",
"ggg",
"hh",
"i",
"jj",
"kkk"
}));
add(comboBox1, "cell 1 5,growx");
@@ -366,7 +377,15 @@ public class FlatComponentsTest
"not editable",
"a",
"bb",
"ccc"
"ccc",
"dd",
"e",
"ff",
"ggg",
"hh",
"i",
"jj",
"kkk"
}));
add(comboBox3, "cell 3 5,growx");
@@ -739,8 +758,9 @@ public class FlatComponentsTest
//======== panel3 ========
{
panel3.setOpaque(false);
panel3.setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets 0,hidemode 3",
// columns
"[]",
// rows
@@ -782,6 +802,7 @@ public class FlatComponentsTest
//======== panel2 ========
{
panel2.setBorder(new TitledBorder("TitledBorder"));
panel2.setOpaque(false);
panel2.setLayout(new FlowLayout());
}
add(panel2, "cell 3 16,grow");

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][][][][]"
"$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][]"
} ) {
@@ -56,10 +56,11 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatComponentsTest$TestDefaultButton" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatComponentsTest$TestDefaultButton" ) {
name: "button5"
"text": "default"
"displayedMnemonicIndex": 0
"toolTipText": "Tool tip with\nmultiple\nlines."
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 1"
} )
@@ -205,6 +206,14 @@ new FormModel {
addElement( "a" )
addElement( "bb" )
addElement( "ccc" )
addElement( "dd" )
addElement( "e" )
addElement( "ff" )
addElement( "ggg" )
addElement( "hh" )
addElement( "i" )
addElement( "jj" )
addElement( "kkk" )
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5,growx"
@@ -231,6 +240,14 @@ new FormModel {
addElement( "a" )
addElement( "bb" )
addElement( "ccc" )
addElement( "dd" )
addElement( "e" )
addElement( "ff" )
addElement( "ggg" )
addElement( "hh" )
addElement( "i" )
addElement( "jj" )
addElement( "kkk" )
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 5,growx"
@@ -696,9 +713,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]"
"$rowConstraints": "[][][]"
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel3"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>"
@@ -742,6 +760,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": new javax.swing.border.TitledBorder( "TitledBorder" )
"opaque": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 16,grow"
} )

View File

@@ -2,7 +2,7 @@
* Created by JFormDesigner on Tue Aug 27 21:47:02 CEST 2019
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import javax.swing.*;
@@ -14,11 +14,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatContainerTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatContainerTest" );
frame.showFrame( new FlatContainerTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatContainerTest" );
frame.showFrame( FlatContainerTest::new );
} );
}
public FlatContainerTest() {
@@ -102,7 +104,7 @@ public class FlatContainerTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3",
"insets dialog,hidemode 3",
// columns
"[grow,fill]",
// rows
@@ -110,6 +112,7 @@ public class FlatContainerTest
//======== panel9 ========
{
panel9.setOpaque(false);
panel9.setLayout(new FormLayout(
"70dlu:grow, $lcgap, 70dlu:grow",
"default, $lgap, fill:70dlu, $lgap, pref, 2*($lgap, fill:70dlu:grow), $lgap, pref"));
@@ -281,6 +284,7 @@ public class FlatContainerTest
//======== panel14 ========
{
panel14.setOpaque(false);
panel14.setLayout(new MigLayout(
"insets 0,hidemode 3",
// columns

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
@@ -17,6 +17,7 @@ new FormModel {
"$rowSpecs": "default, linegap, fill:70dlu, linegap, pref, linegap, fill:70dlu:grow, linegap, fill:70dlu:grow, linegap, pref"
} ) {
name: "panel9"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "splitPaneLabel"
"text": "JSplitPane:"
@@ -203,6 +204,7 @@ new FormModel {
"$rowConstraints": "[center]"
} ) {
name: "panel14"
"opaque": false
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "moreTabsCheckBox"
"text": "more tabs"

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.Color;
import java.awt.Component;
@@ -58,6 +58,7 @@ public class FlatInspector
private Component lastComponent;
private int lastX;
private int lastY;
private boolean inspectParent;
private JComponent highlightFigure;
private JToolTip tip;
@@ -70,6 +71,7 @@ public class FlatInspector
public void mouseMoved( MouseEvent e ) {
lastX = e.getX();
lastY = e.getY();
inspectParent = e.isShiftDown();
inspect( lastX, lastY );
}
} );
@@ -105,6 +107,8 @@ public class FlatInspector
private void inspect( int x, int y ) {
Container contentPane = rootPane.getContentPane();
Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y );
if( inspectParent && c != null && c != contentPane )
c = c.getParent();
if( c == contentPane || (c != null && c.getParent() == contentPane) )
c = null;
@@ -237,8 +241,10 @@ public class FlatInspector
}
text += "Enabled: " + c.isEnabled() + '\n';
text += "Opaque: " + c.isOpaque() + '\n';
text += "Opaque: " + c.isOpaque() + (c instanceof JComponent &&
FlatUIUtils.hasOpaqueBeenExplicitlySet( (JComponent) c ) ? " EXPLICIT" : "") + '\n';
text += "Focusable: " + c.isFocusable() + '\n';
text += "Left-to-right: " + c.getComponentOrientation().isLeftToRight() + '\n';
text += "Parent: " + c.getParent().getClass().getName();
return text;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.Component;
import java.awt.Container;
@@ -26,11 +26,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatMenusTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatMenusTest" );
frame.showFrame( new FlatMenusTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatMenusTest" );
frame.showFrame( FlatMenusTest::new );
} );
}
FlatMenusTest() {
@@ -101,7 +103,7 @@ public class FlatMenusTest
//======== this ========
setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[125]" +
"[]" +
@@ -153,8 +155,9 @@ public class FlatMenusTest
//======== panel1 ========
{
panel1.setOpaque(false);
panel1.setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr",
"ltr,insets 0,hidemode 3",
// columns
"[125,left]" +
"[fill]",
@@ -211,8 +214,9 @@ public class FlatMenusTest
//======== panel2 ========
{
panel2.setOpaque(false);
panel2.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows
@@ -251,8 +255,9 @@ public class FlatMenusTest
//======== panel3 ========
{
panel3.setOpaque(false);
panel3.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows
@@ -290,8 +295,9 @@ public class FlatMenusTest
//======== panel4 ========
{
panel4.setOpaque(false);
panel4.setLayout(new MigLayout(
"insets 0,gap 5 5",
"insets 0",
// columns
"[fill]",
// rows

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[125][][][][]"
"$rowConstraints": "[][top][][]"
} ) {
@@ -50,9 +50,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[125,left][fill]"
"$rowConstraints": "[][][][][]"
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel1"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) {
name: "menuLabel"
"text": "JMenu:"
@@ -121,9 +122,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel2"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu2"
"text": "disabled"
@@ -161,9 +163,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel3"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu3"
"text": "text"
@@ -201,9 +204,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]"
"$layoutConstraints": "insets 0,gap 5 5"
"$layoutConstraints": "insets 0"
} ) {
name: "panel4"
"opaque": false
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu4"
"text": "text"

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.awt.event.MouseAdapter;
@@ -27,11 +27,13 @@ import net.miginfocom.swing.*;
* @author Karl Tauber
*/
public class FlatOptionPaneTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" );
frame.showFrame( new FlatOptionPaneTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" );
frame.showFrame( FlatOptionPaneTest::new );
} );
}
FlatOptionPaneTest() {
@@ -88,7 +90,7 @@ public class FlatOptionPaneTest
//======== this ========
setLayout(new MigLayout(
"flowy,ltr,insets 0,hidemode 3,gap 5 5",
"flowy,ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]" +

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "flowy,ltr,insets 0,hidemode 3,gap 5 5"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "flowy,ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][fill]"
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
} ) {
@@ -30,7 +30,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "plainShowDialogLabel"
"optionPane": new FormReference( "plainOptionPane" )
"titleLabel": new FormReference( "plainLabel" )
@@ -60,7 +60,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "errorShowDialogLabel"
"titleLabel": new FormReference( "errorLabel" )
"optionPane": new FormReference( "errorOptionPane" )
@@ -90,7 +90,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "informationShowDialogLabel"
"optionPane": new FormReference( "informationOptionPane" )
"titleLabel": new FormReference( "informationLabel" )
@@ -120,7 +120,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "questionShowDialogLabel"
"optionPane": new FormReference( "questionOptionPane" )
"titleLabel": new FormReference( "questionLabel" )
@@ -147,7 +147,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "warningShowDialogLabel"
"optionPane": new FormReference( "warningOptionPane" )
"titleLabel": new FormReference( "warningLabel" )
@@ -174,7 +174,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "inputShowDialogLabel"
"optionPane": new FormReference( "inputOptionPane" )
"titleLabel": new FormReference( "inputLabel" )
@@ -202,7 +202,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "inputIconShowDialogLabel"
"titleLabel": new FormReference( "inputIconLabel" )
"optionPane": new FormReference( "inputIconOptionPane" )
@@ -230,7 +230,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7"
} )
add( new FormComponent( "com.formdev.flatlaf.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
add( new FormComponent( "com.formdev.flatlaf.testing.FlatOptionPaneTest$ShowDialogLinkLabel" ) {
name: "customShowDialogLabel"
"optionPane": new FormReference( "customOptionPane" )
"titleLabel": new FormReference( "customLabel" )
@@ -239,7 +239,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 840 )
"size": new java.awt.Dimension( 790, 920 )
} )
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.awt.event.ComponentAdapter;
@@ -23,11 +23,19 @@ import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.extras.TriStateCheckBox.State;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -44,9 +52,12 @@ public class FlatTestFrame
private static final String KEY_SCALE_FACTOR = "scaleFactor";
private final String title;
private Supplier<JComponent> contentFactory;
private JComponent content;
private FlatInspector inspector;
public boolean useApplyComponentOrientation;
public static FlatTestFrame create( String[] args, String title ) {
Preferences prefs = Preferences.userRoot().node( PREFS_ROOT_PATH );
@@ -204,8 +215,9 @@ public class FlatTestFrame
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
}
public void showFrame( JComponent content ) {
this.content = content;
public void showFrame( Supplier<JComponent> contentFactory ) {
this.contentFactory = contentFactory;
this.content = contentFactory.get();
contentPanel.getContentPane().add( content );
pack();
@@ -295,7 +307,7 @@ public class FlatTestFrame
c.setBackground( explicit ? Color.orange : restoreColor );
} else {
c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.red : restoreColor );
c.setBackground( explicit ? Color.green : restoreColor );
}
} );
@@ -306,10 +318,26 @@ public class FlatTestFrame
} );
}
private void backgroundChanged() {
contentPanel.repaint();
}
boolean isPaintBackgroundPattern() {
return backgroundCheckBox.isSelected();
}
private void rightToLeftChanged() {
contentPanel.applyComponentOrientation( rightToLeftCheckBox.isSelected()
ComponentOrientation orientation = rightToLeftCheckBox.isSelected()
? ComponentOrientation.RIGHT_TO_LEFT
: ComponentOrientation.LEFT_TO_RIGHT );
: ComponentOrientation.LEFT_TO_RIGHT;
if( useApplyComponentOrientation )
content.applyComponentOrientation( orientation );
else {
updateComponentsRecur( content, (c, type) -> {
c.setComponentOrientation( orientation );
} );
}
contentPanel.revalidate();
contentPanel.repaint();
}
@@ -380,17 +408,48 @@ public class FlatTestFrame
}
}
private void opaqueChanged() {
State opaque = opaqueTriStateCheckBox.getState();
if( opaque == State.INDETERMINATE )
recreateContent();
else {
updateComponentsRecur( content, (c, type) -> {
if( c instanceof JComponent )
((JComponent)c).setOpaque( opaque == State.SELECTED );
} );
contentPanel.repaint();
}
}
private void recreateContent() {
contentPanel.getContentPane().remove( content );
content = contentFactory.get();
contentPanel.getContentPane().add( content );
if( rightToLeftCheckBox.isSelected() )
rightToLeftChanged();
if( !enabledCheckBox.isSelected() )
enabledChanged();
if( explicitColorsCheckBox.isSelected() )
explicitColorsChanged();
contentPanel.revalidate();
contentPanel.repaint();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
dialogPane = new JPanel();
contentPanel = new JRootPane();
buttonBar = new JPanel();
lookAndFeelComboBox = new JComboBox<>();
explicitColorsCheckBox = new JCheckBox();
scaleFactorComboBox = new JComboBox<>();
rightToLeftCheckBox = new JCheckBox();
enabledCheckBox = new JCheckBox();
inspectCheckBox = new JCheckBox();
scaleFactorComboBox = new JComboBox<>();
explicitColorsCheckBox = new JCheckBox();
backgroundCheckBox = new JCheckBox();
opaqueTriStateCheckBox = new TriStateCheckBox();
closeButton = new JButton();
//======== this ========
@@ -406,7 +465,7 @@ public class FlatTestFrame
{
Container contentPanelContentPane = contentPanel.getContentPane();
contentPanelContentPane.setLayout(new MigLayout(
"insets dialog,hidemode 3",
"insets 0,hidemode 3",
// columns
"[grow,fill]",
// rows
@@ -425,6 +484,8 @@ public class FlatTestFrame
"[fill]" +
"[fill]" +
"[fill]" +
"[fill]" +
"[fill]" +
"[grow,fill]" +
"[button,fill]",
// rows
@@ -434,11 +495,23 @@ public class FlatTestFrame
lookAndFeelComboBox.addActionListener(e -> lookAndFeelChanged());
buttonBar.add(lookAndFeelComboBox, "cell 0 0");
//---- explicitColorsCheckBox ----
explicitColorsCheckBox.setText("explicit colors");
explicitColorsCheckBox.setMnemonic('X');
explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged());
buttonBar.add(explicitColorsCheckBox, "cell 1 0");
//---- scaleFactorComboBox ----
scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"default",
"1",
"1.25",
"1.5",
"1.75",
"2.0",
"2.25",
"2.5",
"3",
"3.5",
"4"
}));
scaleFactorComboBox.setMaximumRowCount(20);
scaleFactorComboBox.addActionListener(e -> scaleFactorChanged());
buttonBar.add(scaleFactorComboBox, "cell 1 0");
//---- rightToLeftCheckBox ----
rightToLeftCheckBox.setText("right-to-left");
@@ -459,27 +532,27 @@ public class FlatTestFrame
inspectCheckBox.addActionListener(e -> inspectChanged());
buttonBar.add(inspectCheckBox, "cell 4 0");
//---- scaleFactorComboBox ----
scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"default",
"1",
"1.25",
"1.5",
"1.75",
"2.0",
"2.25",
"2.5",
"3",
"3.5",
"4"
}));
scaleFactorComboBox.setMaximumRowCount(20);
scaleFactorComboBox.addActionListener(e -> scaleFactorChanged());
buttonBar.add(scaleFactorComboBox, "cell 5 0");
//---- explicitColorsCheckBox ----
explicitColorsCheckBox.setText("explicit colors");
explicitColorsCheckBox.setMnemonic('X');
explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged());
buttonBar.add(explicitColorsCheckBox, "cell 5 0");
//---- backgroundCheckBox ----
backgroundCheckBox.setText("background");
backgroundCheckBox.setMnemonic('B');
backgroundCheckBox.addActionListener(e -> backgroundChanged());
buttonBar.add(backgroundCheckBox, "cell 6 0");
//---- opaqueTriStateCheckBox ----
opaqueTriStateCheckBox.setText("opaque");
opaqueTriStateCheckBox.setMnemonic('O');
opaqueTriStateCheckBox.addActionListener(e -> opaqueChanged());
buttonBar.add(opaqueTriStateCheckBox, "cell 7 0");
//---- closeButton ----
closeButton.setText("Close");
buttonBar.add(closeButton, "cell 7 0");
buttonBar.add(closeButton, "cell 9 0");
}
dialogPane.add(buttonBar, BorderLayout.SOUTH);
}
@@ -492,11 +565,13 @@ public class FlatTestFrame
private JRootPane contentPanel;
private JPanel buttonBar;
private JComboBox<LafInfo> lookAndFeelComboBox;
private JCheckBox explicitColorsCheckBox;
private JComboBox<String> scaleFactorComboBox;
private JCheckBox rightToLeftCheckBox;
private JCheckBox enabledCheckBox;
private JCheckBox inspectCheckBox;
private JComboBox<String> scaleFactorComboBox;
private JCheckBox explicitColorsCheckBox;
private JCheckBox backgroundCheckBox;
private TriStateCheckBox opaqueTriStateCheckBox;
private JButton closeButton;
// JFormDesigner - End of variables declaration //GEN-END:variables

View File

@@ -11,7 +11,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
name: "dialogPane"
add( new FormContainer( "javax.swing.JRootPane", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog,hidemode 3"
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
@@ -21,7 +21,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog"
"$columnConstraints": "[fill][fill][fill][fill][fill][fill][grow,fill][button,fill]"
"$columnConstraints": "[fill][fill][fill][fill][fill][fill][fill][fill][grow,fill][button,fill]"
"$rowSpecs": "[fill]"
} ) {
name: "buttonBar"
@@ -34,11 +34,27 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "explicitColorsCheckBox"
"text": "explicit colors"
"mnemonic": 88
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "scaleFactorComboBox"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "default"
addElement( "default" )
addElement( "1" )
addElement( "1.25" )
addElement( "1.5" )
addElement( "1.75" )
addElement( "2.0" )
addElement( "2.25" )
addElement( "2.5" )
addElement( "3" )
addElement( "3.5" )
addElement( "4" )
}
"maximumRowCount": 20
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scaleFactorChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
@@ -67,35 +83,35 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "scaleFactorComboBox"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "default"
addElement( "default" )
addElement( "1" )
addElement( "1.25" )
addElement( "1.5" )
addElement( "1.75" )
addElement( "2.0" )
addElement( "2.25" )
addElement( "2.5" )
addElement( "3" )
addElement( "3.5" )
addElement( "4" )
}
"maximumRowCount": 20
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scaleFactorChanged", false ) )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "explicitColorsCheckBox"
"text": "explicit colors"
"mnemonic": 88
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "backgroundCheckBox"
"text": "background"
"mnemonic": 66
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "backgroundChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 6 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "opaqueTriStateCheckBox"
"text": "opaque"
"mnemonic": 79
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "opaqueChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 0"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "closeButton"
"text": "Close"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 0"
"value": "cell 9 0"
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "South"

View File

@@ -14,7 +14,9 @@
* limitations under the License.
*/
package com.formdev.flatlaf;
package com.formdev.flatlaf.testing;
import com.formdev.flatlaf.FlatLaf;
/**
* A Flat LaF that has a test color scheme.

View File

@@ -0,0 +1,57 @@
/*
* 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.testing;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* @author Karl Tauber
*/
public class FlatTestPanel
extends JPanel
{
@Override
protected void paintComponent( Graphics g ) {
int width = getWidth();
int height = getHeight();
g.setColor( super.getBackground() );
g.fillRect( 0, 0, width, height );
if( isPaintBackgroundPattern() ) {
g.setColor( Color.magenta );
for( int y = 0; y < height; y += 2 )
g.drawLine( 0, y, width - 1, y );
}
}
/**
* Overridden to see which components paint background with color from parent.
*/
@Override
public Color getBackground() {
return isPaintBackgroundPattern() ? Color.red : super.getBackground();
}
private boolean isPaintBackgroundPattern() {
FlatTestFrame frame = (FlatTestFrame) SwingUtilities.getAncestorOfClass( FlatTestFrame.class, this );
return frame != null && frame.isPaintBackgroundPattern();
}
}

View File

@@ -0,0 +1,103 @@
/*
* 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.testing.extras;
import javax.swing.*;
import com.formdev.flatlaf.extras.*;
import com.formdev.flatlaf.testing.*;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatExtrasTest
extends FlatTestPanel
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatExtrasTest" );
frame.showFrame( FlatExtrasTest::new );
} );
}
public FlatExtrasTest() {
initComponents();
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
triStateLabel2.setText( triStateCheckBox2.getState().toString() );
}
private void triStateCheckBox1Changed() {
triStateLabel1.setText( triStateCheckBox1.getState().toString() );
}
private void triStateCheckBox2Changed() {
triStateLabel2.setText( triStateCheckBox2.getState().toString() );
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel();
triStateCheckBox1 = new TriStateCheckBox();
triStateLabel1 = new JLabel();
triStateCheckBox2 = new TriStateCheckBox();
triStateLabel2 = new JLabel();
//======== this ========
setLayout(new MigLayout(
"ltr,insets dialog,hidemode 3",
// columns
"[]" +
"[]" +
"[left]",
// rows
"[]" +
"[]"));
//---- label1 ----
label1.setText("TriStateCheckBox:");
add(label1, "cell 0 0");
//---- triStateCheckBox1 ----
triStateCheckBox1.setText("three states");
triStateCheckBox1.addActionListener(e -> triStateCheckBox1Changed());
add(triStateCheckBox1, "cell 1 0");
//---- triStateLabel1 ----
triStateLabel1.setText("text");
add(triStateLabel1, "cell 2 0");
//---- triStateCheckBox2 ----
triStateCheckBox2.setText("third state disabled");
triStateCheckBox2.setThirdStateEnabled(false);
triStateCheckBox2.addActionListener(e -> triStateCheckBox2Changed());
add(triStateCheckBox2, "cell 1 1");
//---- triStateLabel2 ----
triStateLabel2.setText("text");
add(triStateLabel2, "cell 2 1");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JLabel label1;
private TriStateCheckBox triStateCheckBox1;
private JLabel triStateLabel1;
private TriStateCheckBox triStateCheckBox2;
private JLabel triStateLabel2;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,50 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][left]"
"$rowConstraints": "[][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "TriStateCheckBox:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "triStateCheckBox1"
"text": "three states"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "triStateCheckBox1Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "triStateLabel1"
"text": "text"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "triStateCheckBox2"
"text": "third state disabled"
"thirdStateEnabled": false
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "triStateCheckBox2Changed", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "triStateLabel2"
"text": "text"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 400, 300 )
} )
}
}

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.testing.swingx;
import java.io.InputStream;
import com.formdev.flatlaf.FlatDefaultsAddon;
/**
* SwingX addon for FlatLaf for testing.
*
* @author Karl Tauber
*/
public class FlatSwingXDefaultsTestAddon
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

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.formdev.flatlaf.swingx;
package com.formdev.flatlaf.testing.swingx;
import java.awt.*;
import java.util.Calendar;
@@ -22,17 +22,21 @@ import java.util.Date;
import javax.swing.*;
import net.miginfocom.swing.*;
import org.jdesktop.swingx.*;
import com.formdev.flatlaf.FlatTestFrame;
import com.formdev.flatlaf.testing.FlatTestFrame;
import com.formdev.flatlaf.testing.FlatTestPanel;
/**
* @author Karl Tauber
*/
public class FlatSwingXTest
extends JPanel
extends FlatTestPanel
{
public static void main( String[] args ) {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSwingXTest" );
frame.showFrame( new FlatSwingXTest() );
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSwingXTest" );
frame.useApplyComponentOrientation = true;
frame.showFrame( FlatSwingXTest::new );
} );
}
FlatSwingXTest() {
@@ -99,7 +103,7 @@ public class FlatSwingXTest
//======== this ========
setLayout(new MigLayout(
"hidemode 3,ltr",
"ltr,insets dialog,hidemode 3",
// columns
"[left]" +
"[]" +
@@ -196,7 +200,7 @@ public class FlatSwingXTest
//---- busyCheckBox ----
busyCheckBox.setText("busy");
busyCheckBox.setMnemonic('B');
busyCheckBox.setMnemonic('Y');
busyCheckBox.addActionListener(e -> busyChanged());
add(busyCheckBox, "cell 2 6");

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3,ltr"
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left][][][fill]"
"$rowConstraints": "[]0[][]0[][][][][]"
} ) {
@@ -144,7 +144,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "busyCheckBox"
"text": "busy"
"mnemonic": 66
"mnemonic": 89
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}

View File

@@ -0,0 +1 @@
com.formdev.flatlaf.testing.swingx.FlatSwingXDefaultsTestAddon

View File

@@ -20,6 +20,7 @@
@selectionBackground=00aa00
@selectionInactiveBackground=888888
@selectionInactiveForeground=ffffff
@disabledText=000088
@textComponentBackground=ffffff
@cellFocusColor=ff0000
@icon=afafaf
@@ -37,8 +38,8 @@
*.selectionBackground=@selectionBackground
*.selectionForeground=ffff00
*.disabledBackground=e0e0e0
*.disabledForeground=000088
*.disabledText=000088
*.disabledForeground=@disabledText
*.disabledText=@disabledText
*.acceleratorForeground=ff8888
*.acceleratorSelectionForeground=ffffff

View File

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