Compare commits

..

18 Commits
0.16 ... 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
58 changed files with 1961 additions and 714 deletions

View File

@@ -1,6 +1,21 @@
FlatLaf Change Log 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 ## 0.16
- Made some fixes for right-to-left support in ComboBox, Slider and ToolTip. - Made some fixes for right-to-left support in ComboBox, Slider and ToolTip.

View File

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

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
version = "0.16" version = "0.17"
allprojects { allprojects {
repositories { 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 { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
tasks { tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) { if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
named<JavaCompile>( "compileModuleInfoJava" ) { named<JavaCompile>( "compileModuleInfoJava" ) {
sourceCompatibility = "9" sourceCompatibility = "9"
@@ -88,19 +90,6 @@ tasks {
from( javadoc ) from( javadoc )
} }
register( "testJar", Jar::class ) {
archiveBaseName.set( "flatlaf-test" )
from( sourceSets.test.get().output )
}
}
configurations {
create( "testArtifacts" )
}
artifacts {
add( "testArtifacts", tasks.getByPath( "testJar" ) )
} }
publishing { publishing {

View File

@@ -27,6 +27,9 @@ public interface FlatClientProperties
String BUTTON_TYPE = "JButton.buttonType"; String BUTTON_TYPE = "JButton.buttonType";
String BUTTON_TYPE_HELP = "help"; 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. * 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.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.Font; import java.awt.Font;
import java.awt.Insets;
import java.awt.KeyEventPostProcessor; import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.Toolkit; import java.awt.Toolkit;
@@ -30,16 +28,7 @@ import java.awt.Window;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; 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.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.AbstractButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
@@ -48,16 +37,9 @@ import javax.swing.SwingUtilities;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException; import javax.swing.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.FontUIResource;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel; 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.SystemInfo;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -69,13 +51,6 @@ import com.formdev.flatlaf.util.UIScale;
public abstract class FlatLaf public abstract class FlatLaf
extends BasicLookAndFeel extends BasicLookAndFeel
{ {
private static final String TYPE_PREFIX = "{";
private static final String TYPE_PREFIX_END = "}";
private static final String VARIABLE_PREFIX = "@";
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
private static final String OPTIONAL_PREFIX = "?";
private static final String GLOBAL_PREFIX = "*.";
private BasicLookAndFeel base; private BasicLookAndFeel base;
private String desktopPropertyName; private String desktopPropertyName;
@@ -209,7 +184,7 @@ public abstract class FlatLaf
Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null; Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null;
initFonts( defaults ); initFonts( defaults );
loadDefaultsFromProperties( defaults ); UIDefaultsLoader.loadDefaultsFromProperties( getClass(), defaults );
// use Aqua MenuBarUI if Mac screen menubar is enabled // use Aqua MenuBarUI if Mac screen menubar is enabled
if( useScreenMenuBar ) if( useScreenMenuBar )
@@ -254,291 +229,8 @@ public abstract class FlatLaf
defaults.put( "MenuItem.acceleratorFont", uiFont ); 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 ) { public static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>(); return UIDefaultsLoader.split( str, delim );
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;
} }
private static void reSetLookAndFeel() { 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; package com.formdev.flatlaf.icons;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.UIManager; import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI; import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/** /**
* Icon for {@link javax.swing.JCheckBox}. * 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.selectedPressedBackground Color optional
* @uiDefault CheckBox.icon.checkmarkColor Color * @uiDefault CheckBox.icon.checkmarkColor Color
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color * @uiDefault CheckBox.icon.disabledCheckmarkColor Color
* @uiDefault CheckBox.arc int
* *
* @author Karl Tauber * @author Karl Tauber
*/ */
@@ -58,6 +63,7 @@ public class FlatCheckBoxIcon
{ {
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" ); protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
protected final Color focusColor = UIManager.getColor( "Component.focusColor" ); 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 borderColor = UIManager.getColor( "CheckBox.icon.borderColor" );
protected final Color disabledBorderColor = UIManager.getColor( "CheckBox.icon.disabledBorderColor" ); protected final Color disabledBorderColor = UIManager.getColor( "CheckBox.icon.disabledBorderColor" );
@@ -84,7 +90,8 @@ public class FlatCheckBoxIcon
@Override @Override
protected void paintIcon( Component c, Graphics2D g2 ) { 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 // paint focused border
if( c.hasFocus() && focusWidth > 0 ) { if( c.hasFocus() && focusWidth > 0 ) {
@@ -102,17 +109,21 @@ public class FlatCheckBoxIcon
paintBorder( g2 ); paintBorder( g2 );
// paint background // paint background
g2.setColor( FlatButtonUI.buttonStateColor( c, FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
selected ? selectedBackground : background, selected ? selectedBackground : background,
disabledBackground, disabledBackground,
focusedBackground, focusedBackground,
selected && selectedHoverBackground != null ? selectedHoverBackground : hoverBackground, selected && selectedHoverBackground != null ? selectedHoverBackground : hoverBackground,
selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ) ); selected && selectedPressedBackground != null ? selectedPressedBackground : pressedBackground ),
background );
paintBackground( g2 ); paintBackground( g2 );
// paint checkmark // paint checkmark
if( selected ) { if( selected || indeterminate ) {
g2.setColor( c.isEnabled() ? checkmarkColor : disabledCheckmarkColor ); g2.setColor( c.isEnabled() ? checkmarkColor : disabledCheckmarkColor );
if( indeterminate )
paintIndeterminate( g2 );
else
paintCheckmark( g2 ); paintCheckmark( g2 );
} }
} }
@@ -120,15 +131,18 @@ public class FlatCheckBoxIcon
protected void paintFocusBorder( Graphics2D g2 ) { protected void paintFocusBorder( Graphics2D g2 ) {
// the outline focus border is painted outside of the icon // the outline focus border is painted outside of the icon
int wh = ICON_SIZE - 1 + (focusWidth * 2); 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 ) { 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 ) { 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 ) { 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.setStroke( new BasicStroke( 1.9f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
g2.draw( path ); 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 java.awt.geom.Path2D;
import javax.swing.UIManager; import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI; import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/** /**
* Help button icon for {@link javax.swing.JButton}. * 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 ) ); g2.fill( new Ellipse2D.Float( focusWidth + 0.5f, focusWidth + 0.5f, 21, 21 ) );
// paint background // paint background
g2.setColor( FlatButtonUI.buttonStateColor( c, FlatUIUtils.setColor( g2, FlatButtonUI.buttonStateColor( c,
background, background,
disabledBackground, disabledBackground,
focusedBackground, focusedBackground,
hoverBackground, hoverBackground,
pressedBackground ) ); pressedBackground ), background );
g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) ); g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) );
// paint question mark // paint question mark

View File

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

View File

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

View File

@@ -190,7 +190,7 @@ public class FlatButtonUI
float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0; float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
float arc = (border instanceof FlatButtonBorder || isToolBarButton( c )) ? scale( (float) this.arc ) : 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 ); FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally { } finally {
g2.dispose(); g2.dispose();

View File

@@ -41,6 +41,7 @@ import javax.swing.JComponent;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.ListCellRenderer; import javax.swing.ListCellRenderer;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.border.AbstractBorder; import javax.swing.border.AbstractBorder;
@@ -123,6 +124,8 @@ public class FlatComboBoxUI
protected void installDefaults() { protected void installDefaults() {
super.installDefaults(); super.installDefaults();
LookAndFeel.installProperty( comboBox, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" ); focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" ); arc = UIManager.getInt( "Component.arc" );
arrowType = UIManager.getString( "Component.arrowType" ); arrowType = UIManager.getString( "Component.arrowType" );
@@ -209,7 +212,7 @@ public class FlatComboBoxUI
String propertyName = e.getPropertyName(); String propertyName = e.getPropertyName();
if( editor != null && if( editor != null &&
((source == comboBox && (propertyName == "background" || propertyName == "foreground")) || ((source == comboBox && propertyName == "foreground") ||
(source == editor && propertyName == "enabled")) ) (source == editor && propertyName == "enabled")) )
{ {
// fix editor component colors // fix editor component colors
@@ -239,6 +242,10 @@ public class FlatComboBoxUI
if( editor instanceof JTextComponent ) if( editor instanceof JTextComponent )
((JTextComponent)editor).setBorder( BorderFactory.createEmptyBorder() ); ((JTextComponent)editor).setBorder( BorderFactory.createEmptyBorder() );
// explicitly make non-opaque
if( editor instanceof JComponent )
((JComponent)editor).setOpaque( false );
editor.applyComponentOrientation( comboBox.getComponentOrientation() ); editor.applyComponentOrientation( comboBox.getComponentOrientation() );
updateEditorColors(); updateEditorColors();
@@ -249,7 +256,6 @@ public class FlatComboBoxUI
// is used, then the editor is updated after the combobox and the // is used, then the editor is updated after the combobox and the
// colors are again replaced with default colors // colors are again replaced with default colors
boolean enabled = editor.isEnabled(); boolean enabled = editor.isEnabled();
editor.setBackground( FlatUIUtils.nonUIResource( enabled ? comboBox.getBackground() : disabledBackground ) );
editor.setForeground( FlatUIUtils.nonUIResource( (enabled || editor instanceof JTextComponent) editor.setForeground( FlatUIUtils.nonUIResource( (enabled || editor instanceof JTextComponent)
? comboBox.getForeground() ? comboBox.getForeground()
: disabledForeground ) ); : disabledForeground ) );
@@ -271,7 +277,8 @@ public class FlatComboBoxUI
@Override @Override
public void update( Graphics g, JComponent c ) { 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 ); FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
@@ -302,14 +309,13 @@ public class FlatComboBoxUI
g2.setClip( oldClip ); g2.setClip( oldClip );
} }
if( comboBox.isEditable() ) {
// paint vertical line between value and arrow button // paint vertical line between value and arrow button
if( comboBox.isEditable() ) {
g2.setColor( enabled ? borderColor : disabledBorderColor ); g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f ); float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw; float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) ); g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
} }
}
paint( g, c ); paint( g, c );
} }

View File

@@ -19,15 +19,12 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.LookAndFeel; import javax.swing.LookAndFeel;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI; import javax.swing.plaf.basic.BasicPasswordFieldUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
/** /**
@@ -46,7 +43,7 @@ public class FlatPasswordFieldUI
protected int focusWidth; protected int focusWidth;
protected int minimumWidth; protected int minimumWidth;
private Handler handler; private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatPasswordFieldUI(); return new FlatPasswordFieldUI();
@@ -63,6 +60,8 @@ public class FlatPasswordFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" ); focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth ); MigLayoutVisualPadding.install( getComponent(), focusWidth );
} }
@@ -77,41 +76,27 @@ public class FlatPasswordFieldUI
protected void installListeners() { protected void installListeners() {
super.installListeners(); super.installListeners();
getComponent().addFocusListener( getHandler() ); focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
} }
@Override @Override
protected void uninstallListeners() { protected void uninstallListeners() {
super.uninstallListeners(); super.uninstallListeners();
getComponent().removeFocusListener( getHandler() ); getComponent().removeFocusListener( focusListener );
focusListener = null;
handler = null;
} }
public Handler getHandler() { @Override
if( handler == null ) protected void paintSafely( Graphics g ) {
handler = new Handler(); FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth );
return handler; super.paintSafely( g );
} }
@Override @Override
protected void paintBackground( Graphics g ) { protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent(); // background is painted elsewhere
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();
}
} }
@Override @Override
@@ -129,20 +114,4 @@ public class FlatPasswordFieldUI
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) ); size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size; 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 java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JProgressBar; import javax.swing.JProgressBar;
import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI; import javax.swing.plaf.basic.BasicProgressBarUI;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -39,6 +40,13 @@ public class FlatProgressBarUI
return new FlatProgressBarUI(); return new FlatProgressBarUI();
} }
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( progressBar, "opaque", false );
}
@Override @Override
protected Dimension getPreferredInnerHorizontal() { protected Dimension getPreferredInnerHorizontal() {
return UIScale.scale( super.getPreferredInnerHorizontal() ); return UIScale.scale( super.getPreferredInnerHorizontal() );

View File

@@ -17,10 +17,8 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.Component; import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Insets; import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ContainerEvent; import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener; import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
@@ -29,10 +27,9 @@ import java.beans.PropertyChangeEvent;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JViewport; import javax.swing.JViewport;
import javax.swing.ScrollPaneLayout; import javax.swing.LookAndFeel;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicScrollPaneUI; import javax.swing.plaf.basic.BasicScrollPaneUI;
/** /**
@@ -53,17 +50,14 @@ public class FlatScrollPaneUI
public void installUI( JComponent c ) { public void installUI( JComponent c ) {
super.installUI( c ); super.installUI( c );
if( scrollpane.getLayout() instanceof UIResource ) int focusWidth = UIManager.getInt( "Component.focusWidth" );
scrollpane.setLayout( new FlatScrollPaneLayout() ); LookAndFeel.installProperty( c, "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( scrollpane, UIManager.getInt( "Component.focusWidth" ) ); MigLayoutVisualPadding.install( scrollpane, focusWidth );
} }
@Override @Override
public void uninstallUI( JComponent c ) { public void uninstallUI( JComponent c ) {
if( scrollpane.getLayout() instanceof FlatScrollPaneLayout )
scrollpane.setLayout( new ScrollPaneLayout.UIResource() );
MigLayoutVisualPadding.uninstall( scrollpane ); MigLayoutVisualPadding.uninstall( scrollpane );
super.uninstallUI( c ); super.uninstallUI( c );
@@ -169,27 +163,4 @@ public class FlatScrollPaneUI
scrollpane.repaint(); 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

@@ -35,6 +35,7 @@ import java.beans.PropertyChangeListener;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JSpinner; import javax.swing.JSpinner;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
@@ -88,6 +89,8 @@ public class FlatSpinnerUI
protected void installDefaults() { protected void installDefaults() {
super.installDefaults(); super.installDefaults();
LookAndFeel.installProperty( spinner, "opaque", false );
focusWidth = UIManager.getInt( "Component.focusWidth" ); focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( "Component.arc" ); arc = UIManager.getInt( "Component.arc" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" );
@@ -152,6 +155,13 @@ public class FlatSpinnerUI
@Override @Override
protected JComponent createEditor() { protected JComponent createEditor() {
JComponent editor = super.createEditor(); JComponent editor = super.createEditor();
// explicitly make non-opaque
editor.setOpaque( false );
JTextField textField = getEditorTextField( editor );
if( textField != null )
textField.setOpaque( false );
updateEditorColors(); updateEditorColors();
return editor; return editor;
} }
@@ -183,8 +193,6 @@ public class FlatSpinnerUI
// use non-UIResource colors because when SwingUtilities.updateComponentTreeUI() // use non-UIResource colors because when SwingUtilities.updateComponentTreeUI()
// is used, then the text field is updated after the spinner and the // is used, then the text field is updated after the spinner and the
// colors are again replaced with default colors // colors are again replaced with default colors
textField.setBackground( FlatUIUtils.nonUIResource( spinner.isEnabled()
? spinner.getBackground() : disabledBackground ) );
textField.setForeground( FlatUIUtils.nonUIResource( spinner.getForeground() ) ); textField.setForeground( FlatUIUtils.nonUIResource( spinner.getForeground() ) );
textField.setDisabledTextColor( FlatUIUtils.nonUIResource( disabledForeground ) ); textField.setDisabledTextColor( FlatUIUtils.nonUIResource( disabledForeground ) );
} }
@@ -225,7 +233,8 @@ public class FlatSpinnerUI
@Override @Override
public void update( Graphics g, JComponent c ) { 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 ); FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
@@ -262,7 +271,6 @@ public class FlatSpinnerUI
float lw = scale( 1f ); float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw; float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) ); g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
}
paint( g, c ); paint( g, c );
} }
@@ -370,7 +378,6 @@ public class FlatSpinnerUI
@Override @Override
public void propertyChange( PropertyChangeEvent e ) { public void propertyChange( PropertyChangeEvent e ) {
switch( e.getPropertyName() ) { switch( e.getPropertyName() ) {
case "background":
case "foreground": case "foreground":
case "enabled": case "enabled":
updateEditorColors(); updateEditorColors();

View File

@@ -21,11 +21,11 @@ import java.awt.Container;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JSpinner; import javax.swing.JSpinner;
import javax.swing.LookAndFeel;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextFieldUI; import javax.swing.plaf.basic.BasicTextFieldUI;
@@ -47,7 +47,7 @@ public class FlatTextFieldUI
protected int focusWidth; protected int focusWidth;
protected int minimumWidth; protected int minimumWidth;
private Handler handler; private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatTextFieldUI(); return new FlatTextFieldUI();
@@ -60,6 +60,8 @@ public class FlatTextFieldUI
focusWidth = UIManager.getInt( "Component.focusWidth" ); focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
MigLayoutVisualPadding.install( getComponent(), focusWidth ); MigLayoutVisualPadding.install( getComponent(), focusWidth );
} }
@@ -74,38 +76,51 @@ public class FlatTextFieldUI
protected void installListeners() { protected void installListeners() {
super.installListeners(); super.installListeners();
getComponent().addFocusListener( getHandler() ); focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
getComponent().addFocusListener( focusListener );
} }
@Override @Override
protected void uninstallListeners() { protected void uninstallListeners() {
super.uninstallListeners(); super.uninstallListeners();
getComponent().removeFocusListener( getHandler() ); getComponent().removeFocusListener( focusListener );
focusListener = null;
handler = null;
} }
public Handler getHandler() { @Override
if( handler == null ) protected void paintSafely( Graphics g ) {
handler = new Handler(); paintBackground( g, getComponent(), focusWidth );
return handler; super.paintSafely( g );
} }
@Override @Override
protected void paintBackground( Graphics g ) { protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent(); // background is painted elsewhere
}
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 ); FlatUIUtils.paintParentBackground( g, c );
// paint background
Graphics2D g2 = (Graphics2D) g.create(); Graphics2D g2 = (Graphics2D) g.create();
try { try {
FlatUIUtils.setRenderingHints( g2 ); 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() ); 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 { } finally {
g2.dispose(); g2.dispose();
} }
@@ -132,20 +147,4 @@ public class FlatTextFieldUI
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) ); size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
return size; 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

@@ -26,6 +26,8 @@ import java.awt.Insets;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.Shape; import java.awt.Shape;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
@@ -33,8 +35,10 @@ import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.JavaCompatibility; import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -101,6 +105,12 @@ public class FlatUIUtils
MAC_USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE ); 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. * Draws a round rectangle.
*/ */
@@ -246,15 +256,23 @@ public class FlatUIUtils
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y ); 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 ------------------------------------------------ //---- class HoverListener ------------------------------------------------
public static class HoverListener public static class HoverListener
extends MouseAdapter extends MouseAdapter
{ {
private final JComponent repaintComponent; private final Component repaintComponent;
private final Consumer<Boolean> hoverChanged; private final Consumer<Boolean> hoverChanged;
public HoverListener( JComponent repaintComponent, Consumer<Boolean> hoverChanged ) { public HoverListener( Component repaintComponent, Consumer<Boolean> hoverChanged ) {
this.repaintComponent = repaintComponent; this.repaintComponent = repaintComponent;
this.hoverChanged = hoverChanged; this.hoverChanged = hoverChanged;
} }
@@ -276,4 +294,26 @@ public class FlatUIUtils
repaintComponent.repaint(); 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

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

View File

@@ -77,6 +77,7 @@ Button.default.borderWidth=1
CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon
CheckBox.arc=2
CheckBox.margin=2,2,2,2 CheckBox.margin=2,2,2,2
CheckBox.iconTextGap=4 CheckBox.iconTextGap=4
CheckBox.rollover=true CheckBox.rollover=true
@@ -277,6 +278,7 @@ ScrollBar.width=10
ScrollPane.border=com.formdev.flatlaf.ui.FlatBorder ScrollPane.border=com.formdev.flatlaf.ui.FlatBorder
ScrollPane.background=@@ScrollBar.track ScrollPane.background=@@ScrollBar.track
ScrollPane.fillUpperCorner=true
#---- Separator ---- #---- Separator ----

View File

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

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 groupId: com.formdev
artifactId: flatlaf-swingx artifactId: flatlaf-swingx
version: 0.16 version: 0.17
Otherwise download `flatlaf-swingx-<version>.jar` here: Otherwise download `flatlaf-swingx-<version>.jar` here:

View File

@@ -25,10 +25,6 @@ plugins {
dependencies { dependencies {
implementation( project( ":flatlaf-core" ) ) implementation( project( ":flatlaf-core" ) )
implementation( "org.swinglabs.swingx:swingx-all:1.6.5-1" ) 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 { java {
@@ -37,6 +33,12 @@ java {
} }
tasks { tasks {
assemble {
dependsOn(
"sourcesJar",
"javadocJar"
)
}
javadoc { javadoc {
options { options {

View File

@@ -28,8 +28,6 @@ import java.awt.Insets;
import java.awt.LayoutManager; import java.awt.LayoutManager;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Shape; import java.awt.Shape;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.text.ParseException; import java.text.ParseException;
import java.util.Calendar; import java.util.Calendar;
@@ -105,6 +103,8 @@ public class FlatDatePickerUI
super.installUI( c ); super.installUI( c );
LookAndFeel.installProperty( datePicker, "opaque", false );
// hack JXDatePicker.TodayPanel colors // hack JXDatePicker.TodayPanel colors
// (there is no need to uninstall these changes because only UIResources are used, // (there is no need to uninstall these changes because only UIResources are used,
// which are automatically replaced when switching LaF) // which are automatically replaced when switching LaF)
@@ -159,18 +159,7 @@ public class FlatDatePickerUI
editor.setName( "dateField" ); editor.setName( "dateField" );
editor.setBorder( BorderFactory.createEmptyBorder() ); editor.setBorder( BorderFactory.createEmptyBorder() );
editor.setOpaque( false ); editor.setOpaque( false );
editor.addFocusListener( new FocusListener() { editor.addFocusListener( new FlatUIUtils.RepaintFocusListener( datePicker ) );
@Override
public void focusLost( FocusEvent e ) {
if( datePicker != null )
datePicker.repaint();
}
@Override
public void focusGained( FocusEvent e ) {
if( datePicker != null )
datePicker.repaint();
}
} );
return editor; return editor;
} }
@@ -230,7 +219,8 @@ public class FlatDatePickerUI
@Override @Override
public void update( Graphics g, JComponent c ) { 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 ); FlatUIUtils.paintParentBackground( g, c );
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
@@ -266,7 +256,6 @@ public class FlatDatePickerUI
float lw = scale( 1f ); float lw = scale( 1f );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw; float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) ); g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
}
paint( g, c ); 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. * limitations under the License.
*/ */
package com.formdev.flatlaf; package com.formdev.flatlaf.testing;
import javax.swing.*; import javax.swing.*;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
@@ -23,12 +23,12 @@ import net.miginfocom.swing.*;
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatChooserTest public class FlatChooserTest
extends JPanel extends FlatTestPanel
{ {
public static void main( String[] args ) { public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> { SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" ); FlatTestFrame frame = FlatTestFrame.create( args, "FlatChooserTest" );
frame.showFrame( new FlatChooserTest() ); frame.showFrame( FlatChooserTest::new );
} ); } );
} }
@@ -56,7 +56,7 @@ public class FlatChooserTest
//======== this ======== //======== this ========
setLayout(new MigLayout( setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr", "ltr,insets dialog,hidemode 3",
// columns // columns
"[]" + "[]" +
"[]", "[]",

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.formdev.flatlaf; package com.formdev.flatlaf.testing;
import java.awt.*; import java.awt.*;
import javax.swing.*; import javax.swing.*;
@@ -25,12 +25,12 @@ import net.miginfocom.swing.*;
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatComponentsTest public class FlatComponentsTest
extends JPanel extends FlatTestPanel
{ {
public static void main( String[] args ) { public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> { SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" ); FlatTestFrame frame = FlatTestFrame.create( args, "FlatComponentsTest" );
frame.showFrame( new FlatComponentsTest() ); frame.showFrame( FlatComponentsTest::new );
} ); } );
} }
@@ -178,7 +178,7 @@ public class FlatComponentsTest
//======== this ======== //======== this ========
setLayout(new MigLayout( setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr", "ltr,insets dialog,hidemode 3",
// columns // columns
"[]" + "[]" +
"[]" + "[]" +
@@ -758,8 +758,9 @@ public class FlatComponentsTest
//======== panel3 ======== //======== panel3 ========
{ {
panel3.setOpaque(false);
panel3.setLayout(new MigLayout( panel3.setLayout(new MigLayout(
"insets 0,hidemode 3,gap 5 5,ltr", "ltr,insets 0,hidemode 3",
// columns // columns
"[]", "[]",
// rows // rows
@@ -801,6 +802,7 @@ public class FlatComponentsTest
//======== panel2 ======== //======== panel2 ========
{ {
panel2.setBorder(new TitledBorder("TitledBorder")); panel2.setBorder(new TitledBorder("TitledBorder"));
panel2.setOpaque(false);
panel2.setLayout(new FlowLayout()); panel2.setLayout(new FlowLayout());
} }
add(panel2, "cell 3 16,grow"); add(panel2, "cell 3 16,grow");

View File

@@ -6,8 +6,8 @@ new FormModel {
auxiliary() { auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true "JavaCodeGenerator.defaultVariableLocal": true
} }
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][][][][]" "$columnConstraints": "[][][][][][]"
"$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][]" "$rowConstraints": "[][][][][][][][][][][][][][][][][][][][][][]"
} ) { } ) {
@@ -56,7 +56,7 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1" "value": "cell 2 1"
} ) } )
add( new FormComponent( "com.formdev.flatlaf.FlatComponentsTest$TestDefaultButton" ) { add( new FormComponent( "com.formdev.flatlaf.testing.FlatComponentsTest$TestDefaultButton" ) {
name: "button5" name: "button5"
"text": "default" "text": "default"
"displayedMnemonicIndex": 0 "displayedMnemonicIndex": 0
@@ -713,9 +713,10 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[]" "$columnConstraints": "[]"
"$rowConstraints": "[][][]" "$rowConstraints": "[][][]"
"$layoutConstraints": "insets 0,hidemode 3,gap 5 5,ltr" "$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) { } ) {
name: "panel3" name: "panel3"
"opaque": false
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3" name: "label3"
"text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>" "text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u></html>"
@@ -759,6 +760,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2" name: "panel2"
"border": new javax.swing.border.TitledBorder( "TitledBorder" ) "border": new javax.swing.border.TitledBorder( "TitledBorder" )
"opaque": false
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 16,grow" "value": "cell 3 16,grow"
} ) } )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.formdev.flatlaf; package com.formdev.flatlaf.testing;
import java.awt.*; import java.awt.*;
import java.awt.event.ComponentAdapter; import java.awt.event.ComponentAdapter;
@@ -23,11 +23,19 @@ import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel; 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.ui.FlatUIUtils;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -44,6 +52,7 @@ public class FlatTestFrame
private static final String KEY_SCALE_FACTOR = "scaleFactor"; private static final String KEY_SCALE_FACTOR = "scaleFactor";
private final String title; private final String title;
private Supplier<JComponent> contentFactory;
private JComponent content; private JComponent content;
private FlatInspector inspector; private FlatInspector inspector;
@@ -206,8 +215,9 @@ public class FlatTestFrame
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
} }
public void showFrame( JComponent content ) { public void showFrame( Supplier<JComponent> contentFactory ) {
this.content = content; this.contentFactory = contentFactory;
this.content = contentFactory.get();
contentPanel.getContentPane().add( content ); contentPanel.getContentPane().add( content );
pack(); pack();
@@ -297,7 +307,7 @@ public class FlatTestFrame
c.setBackground( explicit ? Color.orange : restoreColor ); c.setBackground( explicit ? Color.orange : restoreColor );
} else { } else {
c.setForeground( explicit ? Color.blue : restoreColor ); c.setForeground( explicit ? Color.blue : restoreColor );
c.setBackground( explicit ? Color.red : restoreColor ); c.setBackground( explicit ? Color.green : restoreColor );
} }
} ); } );
@@ -308,6 +318,14 @@ public class FlatTestFrame
} ); } );
} }
private void backgroundChanged() {
contentPanel.repaint();
}
boolean isPaintBackgroundPattern() {
return backgroundCheckBox.isSelected();
}
private void rightToLeftChanged() { private void rightToLeftChanged() {
ComponentOrientation orientation = rightToLeftCheckBox.isSelected() ComponentOrientation orientation = rightToLeftCheckBox.isSelected()
? ComponentOrientation.RIGHT_TO_LEFT ? ComponentOrientation.RIGHT_TO_LEFT
@@ -390,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() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
dialogPane = new JPanel(); dialogPane = new JPanel();
contentPanel = new JRootPane(); contentPanel = new JRootPane();
buttonBar = new JPanel(); buttonBar = new JPanel();
lookAndFeelComboBox = new JComboBox<>(); lookAndFeelComboBox = new JComboBox<>();
explicitColorsCheckBox = new JCheckBox(); scaleFactorComboBox = new JComboBox<>();
rightToLeftCheckBox = new JCheckBox(); rightToLeftCheckBox = new JCheckBox();
enabledCheckBox = new JCheckBox(); enabledCheckBox = new JCheckBox();
inspectCheckBox = new JCheckBox(); inspectCheckBox = new JCheckBox();
scaleFactorComboBox = new JComboBox<>(); explicitColorsCheckBox = new JCheckBox();
backgroundCheckBox = new JCheckBox();
opaqueTriStateCheckBox = new TriStateCheckBox();
closeButton = new JButton(); closeButton = new JButton();
//======== this ======== //======== this ========
@@ -416,7 +465,7 @@ public class FlatTestFrame
{ {
Container contentPanelContentPane = contentPanel.getContentPane(); Container contentPanelContentPane = contentPanel.getContentPane();
contentPanelContentPane.setLayout(new MigLayout( contentPanelContentPane.setLayout(new MigLayout(
"insets dialog,hidemode 3", "insets 0,hidemode 3",
// columns // columns
"[grow,fill]", "[grow,fill]",
// rows // rows
@@ -435,6 +484,8 @@ public class FlatTestFrame
"[fill]" + "[fill]" +
"[fill]" + "[fill]" +
"[fill]" + "[fill]" +
"[fill]" +
"[fill]" +
"[grow,fill]" + "[grow,fill]" +
"[button,fill]", "[button,fill]",
// rows // rows
@@ -444,11 +495,23 @@ public class FlatTestFrame
lookAndFeelComboBox.addActionListener(e -> lookAndFeelChanged()); lookAndFeelComboBox.addActionListener(e -> lookAndFeelChanged());
buttonBar.add(lookAndFeelComboBox, "cell 0 0"); buttonBar.add(lookAndFeelComboBox, "cell 0 0");
//---- explicitColorsCheckBox ---- //---- scaleFactorComboBox ----
explicitColorsCheckBox.setText("explicit colors"); scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
explicitColorsCheckBox.setMnemonic('X'); "default",
explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged()); "1",
buttonBar.add(explicitColorsCheckBox, "cell 1 0"); "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 ----
rightToLeftCheckBox.setText("right-to-left"); rightToLeftCheckBox.setText("right-to-left");
@@ -469,27 +532,27 @@ public class FlatTestFrame
inspectCheckBox.addActionListener(e -> inspectChanged()); inspectCheckBox.addActionListener(e -> inspectChanged());
buttonBar.add(inspectCheckBox, "cell 4 0"); buttonBar.add(inspectCheckBox, "cell 4 0");
//---- scaleFactorComboBox ---- //---- explicitColorsCheckBox ----
scaleFactorComboBox.setModel(new DefaultComboBoxModel<>(new String[] { explicitColorsCheckBox.setText("explicit colors");
"default", explicitColorsCheckBox.setMnemonic('X');
"1", explicitColorsCheckBox.addActionListener(e -> explicitColorsChanged());
"1.25", buttonBar.add(explicitColorsCheckBox, "cell 5 0");
"1.5",
"1.75", //---- backgroundCheckBox ----
"2.0", backgroundCheckBox.setText("background");
"2.25", backgroundCheckBox.setMnemonic('B');
"2.5", backgroundCheckBox.addActionListener(e -> backgroundChanged());
"3", buttonBar.add(backgroundCheckBox, "cell 6 0");
"3.5",
"4" //---- opaqueTriStateCheckBox ----
})); opaqueTriStateCheckBox.setText("opaque");
scaleFactorComboBox.setMaximumRowCount(20); opaqueTriStateCheckBox.setMnemonic('O');
scaleFactorComboBox.addActionListener(e -> scaleFactorChanged()); opaqueTriStateCheckBox.addActionListener(e -> opaqueChanged());
buttonBar.add(scaleFactorComboBox, "cell 5 0"); buttonBar.add(opaqueTriStateCheckBox, "cell 7 0");
//---- closeButton ---- //---- closeButton ----
closeButton.setText("Close"); closeButton.setText("Close");
buttonBar.add(closeButton, "cell 7 0"); buttonBar.add(closeButton, "cell 9 0");
} }
dialogPane.add(buttonBar, BorderLayout.SOUTH); dialogPane.add(buttonBar, BorderLayout.SOUTH);
} }
@@ -502,11 +565,13 @@ public class FlatTestFrame
private JRootPane contentPanel; private JRootPane contentPanel;
private JPanel buttonBar; private JPanel buttonBar;
private JComboBox<LafInfo> lookAndFeelComboBox; private JComboBox<LafInfo> lookAndFeelComboBox;
private JCheckBox explicitColorsCheckBox; private JComboBox<String> scaleFactorComboBox;
private JCheckBox rightToLeftCheckBox; private JCheckBox rightToLeftCheckBox;
private JCheckBox enabledCheckBox; private JCheckBox enabledCheckBox;
private JCheckBox inspectCheckBox; private JCheckBox inspectCheckBox;
private JComboBox<String> scaleFactorComboBox; private JCheckBox explicitColorsCheckBox;
private JCheckBox backgroundCheckBox;
private TriStateCheckBox opaqueTriStateCheckBox;
private JButton closeButton; private JButton closeButton;
// JFormDesigner - End of variables declaration //GEN-END:variables // 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 ) ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
name: "dialogPane" name: "dialogPane"
add( new FormContainer( "javax.swing.JRootPane", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { 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]" "$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]" "$rowConstraints": "[grow,fill]"
} ) { } ) {
@@ -21,7 +21,7 @@ new FormModel {
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets dialog" "$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]" "$rowSpecs": "[fill]"
} ) { } ) {
name: "buttonBar" name: "buttonBar"
@@ -34,11 +34,27 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0" "value": "cell 0 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JComboBox" ) {
name: "explicitColorsCheckBox" name: "scaleFactorComboBox"
"text": "explicit colors" "model": new javax.swing.DefaultComboBoxModel {
"mnemonic": 88 selectedItem: "default"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) ) 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 ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0" "value": "cell 1 0"
} ) } )
@@ -67,35 +83,35 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 0" "value": "cell 4 0"
} ) } )
add( new FormComponent( "javax.swing.JComboBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "scaleFactorComboBox" name: "explicitColorsCheckBox"
"model": new javax.swing.DefaultComboBoxModel { "text": "explicit colors"
selectedItem: "default" "mnemonic": 88
addElement( "default" ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "explicitColorsChanged", false ) )
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 ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 0" "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" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "closeButton" name: "closeButton"
"text": "Close" "text": "Close"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 7 0" "value": "cell 9 0"
} ) } )
}, new FormLayoutConstraints( class java.lang.String ) { }, new FormLayoutConstraints( class java.lang.String ) {
"value": "South" "value": "South"

View File

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

View File

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

View File

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

View File

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