basic implementation of FlatLaf and FlatLabelUI

This commit is contained in:
Karl Tauber
2019-08-19 17:13:47 +02:00
parent 840c3698ad
commit 91a3d64a8e
12 changed files with 606 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
/*
* 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;
/**
* A Flat LaF that has a dark color scheme.
*
* @author Karl Tauber
*/
public class FlatDarkLaf
extends FlatLaf
{
@Override
public String getName() {
return "Flat Dark";
}
@Override
public String getDescription() {
return "Flat Dark Look and Feel";
}
}

View File

@@ -0,0 +1,212 @@
/*
* 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.Font;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.swing.UIDefaults;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.formdev.flatlaf.util.SystemInfo;
/**
* The base class for all Flat LaFs.
*
* @author Karl Tauber
*/
public abstract class FlatLaf
extends BasicLookAndFeel
{
private BasicLookAndFeel base;
@Override
public String getID() {
return getName();
}
@Override
public boolean isNativeLookAndFeel() {
return true;
}
@Override
public boolean isSupportedLookAndFeel() {
return true;
}
@Override
public void initialize() {
getBase().initialize();
super.initialize();
}
@Override
public void uninitialize() {
if( base != null )
base.uninitialize();
super.uninitialize();
}
/**
* Get/create base LaF. This is used to grab base UI defaults from different LaFs.
* E.g. on Mac from system dependent LaF, otherwise from Metal LaF.
*/
private BasicLookAndFeel getBase() {
if( base == null )
base = new MetalLookAndFeel();
return base;
}
@Override
public UIDefaults getDefaults() {
UIDefaults defaults = getBase().getDefaults();
initFonts( defaults );
loadDefaultsFromProperties( defaults );
return defaults;
}
private void initFonts( UIDefaults defaults ) {
FontUIResource uiFont = null;
//TODO
if( SystemInfo.IS_WINDOWS ) {
Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" );
if( winFont != null )
uiFont = new FontUIResource( winFont );
}
if( uiFont == null )
return;
// override fonts
for( Object key : defaults.keySet() ) {
if( key instanceof String && ((String)key).endsWith( ".font" ) )
defaults.put( key, 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();
for( Class<?> lafClass : lafClasses ) {
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
if( in != null )
properties.load( in );
}
}
// get globals, which override all other defaults that end with same suffix
String globalPrefix = "*.";
HashMap<String, Object> globals = new HashMap<>();
for( Object okey : properties.keySet() ) {
String key = (String) okey;
if( key.startsWith( globalPrefix ) ) {
Object value = parseValue( key, properties.getProperty( key ) );
globals.put( key.substring( globalPrefix.length() ), value );
}
}
// 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();
String value = (String) e.getValue();
defaults.put( key, parseValue( key, value ) );
}
} catch( IOException ex ) {
ex.printStackTrace();
}
}
private Object parseValue( String key, String value ) {
value = value.trim();
// null, false, true
switch( value ) {
case "null": return null;
case "false": return false;
case "true": return true;
}
// colors
ColorUIResource color = parseColor( value );
if( color != null )
return color;
// string
return value;
}
private ColorUIResource parseColor( String value ) {
try {
if( value.length() == 6 ) {
int rgb = Integer.parseInt( value, 16 );
return new ColorUIResource( rgb );
}
if( value.length() == 8 ) {
int rgba = Integer.parseInt( value, 16 );
return new ColorUIResource( new Color( rgba, true ) );
}
} catch( NumberFormatException ex ) {
// not a color --> ignore
}
return null;
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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;
/**
* A Flat LaF that has a light color scheme.
*
* @author Karl Tauber
*/
public class FlatLightLaf
extends FlatLaf
{
@Override
public String getName() {
return "Flat Light";
}
@Override
public String getDescription() {
return "Flat Light Look and Feel";
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.ui;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicLabelUI;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JLabel}.
*
* @author Karl Tauber
*/
public class FlatLabelUI
extends BasicLabelUI
{
private static ComponentUI instance;
public static ComponentUI createUI( JComponent c ) {
if( instance == null )
instance = new FlatLabelUI();
return instance;
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.util.Locale;
/**
* Provides information about the current system.
*
* @author Karl Tauber
*/
public class SystemInfo
{
public static final boolean IS_WINDOWS;
public static final boolean IS_MAC;
public static final boolean IS_LINUX;
static {
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
IS_WINDOWS = osName.startsWith( "windows" );
IS_MAC = osName.startsWith( "mac" );
IS_LINUX = osName.startsWith( "linux" );
}
}

View File

@@ -0,0 +1,20 @@
#
# 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.
#
#---- globals ----
*.background=3c3f41
*.foreground=bbbbbb

View File

@@ -0,0 +1,19 @@
#
# Copyright 2019 FormDev Software GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#---- UI delegates ----
LabelUI=com.formdev.flatlaf.ui.FlatLabelUI

View File

@@ -0,0 +1,20 @@
#
# 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.
#
#---- globals ----
*.background=f2f2f2
*.foreground=000000

View File

@@ -0,0 +1,86 @@
/*
* 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.*;
import javax.swing.*;
/**
* @author Karl Tauber
*/
public class FlatComponentsTest
extends JPanel
{
public static void main( String[] args ) {
try {
if( args.length > 0 )
UIManager.setLookAndFeel( args[0] );
else
UIManager.setLookAndFeel( new FlatTestLaf() );
} catch( Exception ex ) {
ex.printStackTrace();
}
JOptionPane.showMessageDialog( null,
new FlatComponentsTest(),
"FlatComponentsTest",
JOptionPane.PLAIN_MESSAGE );
}
public FlatComponentsTest() {
initComponents();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel labelLabel = new JLabel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
//======== this ========
setLayout(new GridBagLayout());
((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0, 0};
((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0};
((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 0.0, 1.0E-4};
((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0E-4};
//---- labelLabel ----
labelLabel.setText("JLabel:");
add(labelLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- label1 ----
label1.setText("enabled");
label1.setDisplayedMnemonic('E');
add(label1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- label2 ----
label2.setText("disabled");
label2.setDisplayedMnemonic('D');
label2.setEnabled(false);
add(label2, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,42 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
auxiliary() {
"JavaCodeGenerator.defaultVariableLocal": true
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.GridBagLayout ) {
"$columnSpecs": "0, 0, 0"
"$rowSpecs": "0"
"$hGap": 5
"$vGap": 5
"$alignLeft": true
"$alignTop": true
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "labelLabel"
"text": "JLabel:"
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "enabled"
"displayedMnemonic": 69
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 1
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "disabled"
"displayedMnemonic": 68
"enabled": false
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 2
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 580, 300 )
} )
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf;
/**
* A Flat LaF that has a test color scheme.
*
* Used to develop Flat LaF.
*
* @author Karl Tauber
*/
public class FlatTestLaf
extends FlatLaf
{
@Override
public String getName() {
return "Flat Test";
}
@Override
public String getDescription() {
return "Flat Test Look and Feel";
}
}

View File

@@ -0,0 +1,20 @@
#
# 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.
#
#---- globals ----
*.background=ccffcc
*.foreground=ff0000