From 91a3d64a8e120653fb0117547a3d66f45bb71f4a Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 19 Aug 2019 17:13:47 +0200 Subject: [PATCH] basic implementation of FlatLaf and FlatLabelUI --- .../java/com/formdev/flatlaf/FlatDarkLaf.java | 36 +++ .../java/com/formdev/flatlaf/FlatLaf.java | 212 ++++++++++++++++++ .../com/formdev/flatlaf/FlatLightLaf.java | 36 +++ .../com/formdev/flatlaf/ui/FlatLabelUI.java | 38 ++++ .../com/formdev/flatlaf/util/SystemInfo.java | 39 ++++ .../formdev/flatlaf/FlatDarkLaf.properties | 20 ++ .../com/formdev/flatlaf/FlatLaf.properties | 19 ++ .../formdev/flatlaf/FlatLightLaf.properties | 20 ++ .../formdev/flatlaf/FlatComponentsTest.java | 86 +++++++ .../formdev/flatlaf/FlatComponentsTest.jfd | 42 ++++ .../java/com/formdev/flatlaf/FlatTestLaf.java | 38 ++++ .../formdev/flatlaf/FlatTestLaf.properties | 20 ++ 12 files changed, 606 insertions(+) create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/FlatDarkLaf.java create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLightLaf.java create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemInfo.java create mode 100644 flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties create mode 100644 flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties create mode 100644 flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestLaf.java create mode 100644 flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatDarkLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatDarkLaf.java new file mode 100644 index 00000000..91f9459d --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatDarkLaf.java @@ -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"; + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java new file mode 100644 index 00000000..16668d1e --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -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> 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 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 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; + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLightLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLightLaf.java new file mode 100644 index 00000000..48b1830b --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLightLaf.java @@ -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"; + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java new file mode 100644 index 00000000..901f4bc9 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java @@ -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; + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemInfo.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemInfo.java new file mode 100644 index 00000000..112cf147 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/SystemInfo.java @@ -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" ); + } +} diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties new file mode 100644 index 00000000..c22de3a9 --- /dev/null +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties @@ -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 diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties new file mode 100644 index 00000000..71533deb --- /dev/null +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -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 diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties new file mode 100644 index 00000000..354dba91 --- /dev/null +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -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 diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java new file mode 100644 index 00000000..bae0f97a --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java @@ -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 +} diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd new file mode 100644 index 00000000..8dae6c9a --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd @@ -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 ) + } ) + } +} diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestLaf.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestLaf.java new file mode 100644 index 00000000..bb7a5d03 --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatTestLaf.java @@ -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"; + } +} diff --git a/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties new file mode 100644 index 00000000..bb0b26f3 --- /dev/null +++ b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties @@ -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