Button: basic border and background

This commit is contained in:
Karl Tauber
2019-08-20 11:13:03 +02:00
parent 85cfd9750c
commit 8ba5c9a39c
10 changed files with 390 additions and 8 deletions

View File

@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import javax.swing.UIDefaults; import javax.swing.UIDefaults;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.FontUIResource; import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.plaf.basic.BasicLookAndFeel;
@@ -202,6 +203,10 @@ public abstract class FlatLaf
case "true": return true; case "true": return true;
} }
// borders
if( key.endsWith( ".border" ) )
return parseBorder( value );
// colors // colors
ColorUIResource color = parseColor( value ); ColorUIResource color = parseColor( value );
if( color != null ) if( color != null )
@@ -211,6 +216,17 @@ public abstract class FlatLaf
return value; return value;
} }
private Object parseBorder( String value ) {
return (LazyValue) t -> {
try {
return Class.forName( value ).newInstance();
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
ex.printStackTrace();
return null;
}
};
}
private ColorUIResource parseColor( String value ) { private ColorUIResource parseColor( String value ) {
try { try {
if( value.length() == 6 ) { if( value.length() == 6 ) {

View File

@@ -0,0 +1,87 @@
/*
* 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 java.awt.Color;
import java.awt.Component;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicBorders;
/**
* Border for {@link javax.swing.JButton}.
*
* @author Karl Tauber
*/
public class FlatButtonBorder
extends BasicBorders.MarginBorder
{
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
float focusWidth = getFocusWidth();
float lineWidth = getLineWidth();
float arc = 6; //TODO
g2.setPaint( getBorderColor( c ) );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, lineWidth, arc );
} finally {
g2.dispose();
}
}
public Paint getBorderColor( Component c ) {
if( c.isEnabled() ) {
Color startColor = UIManager.getColor( "Button.startBorderColor" );
Color endColor = UIManager.getColor( "Button.endBorderColor" );
return (startColor.equals( endColor ) )
? startColor
: new GradientPaint( 0, getFocusWidth(), startColor,
0, c.getHeight() - getFocusWidth() - 1f, endColor );
} else
return UIManager.getColor( "Button.disabledBorderColor" );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
int w = Math.round( getFocusWidth() + getLineWidth() );
insets = super.getBorderInsets( c, insets );
insets.top += w;
insets.left += w;
insets.bottom += w;
insets.right += w;
return insets;
}
protected float getFocusWidth() {
//TODO
return 2;
}
protected float getLineWidth() {
//TODO
return 1;
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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 java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JButton}.
*
* @author Karl Tauber
*/
public class FlatButtonUI
extends BasicButtonUI
{
private static ComponentUI instance;
public static ComponentUI createUI( JComponent c ) {
if( instance == null )
instance = new FlatButtonUI();
return instance;
}
@Override
public void update( Graphics g, JComponent c ) {
if( c.isOpaque() ) {
FlatUIUtils.paintParentBackground( g, c );
if( c.isEnabled() ) {
Graphics2D g2 = (Graphics2D) g.create();
try {
FlatUIUtils.setRenderingHints( g2 );
//TODO
float focusWidth = 2;
float arc = 6;
g2.setColor( c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();
}
}
}
paint( g, c );
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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 java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
/**
* Utility methods for UI delegates.
*
* @author Karl Tauber
*/
public class FlatUIUtils
{
public static final boolean MAC_USE_QUARTZ = Boolean.getBoolean( "apple.awt.graphics.UseQuartz" );
/**
* Sets rendering hints used for painting.
*/
public static void setRenderingHints( Graphics2D g ) {
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL,
MAC_USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE );
}
/**
* Draws a round rectangle.
*/
public static void drawRoundRectangle( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
RoundRectangle2D.Float r1 = new RoundRectangle2D.Float(
x + focusWidth, y + focusWidth,
width - focusWidth * 2, height - focusWidth * 2, arc, arc );
RoundRectangle2D.Float r2 = new RoundRectangle2D.Float(
r1.x + lineWidth, r1.y + lineWidth,
r1.width - lineWidth * 2, r1.height - lineWidth * 2, arc2, arc2 );
Path2D border = new Path2D.Float( Path2D.WIND_EVEN_ODD );
border.append( r1, false );
border.append( r2, false );
g.fill( border );
}
/**
* Fills a round rectangle.
*/
public static void fillRoundRectangle( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float arc )
{
g.fill( new RoundRectangle2D.Float(
x + focusWidth, y + focusWidth,
width - focusWidth * 2, height - focusWidth * 2, arc, arc ) );
}
/**
* Fill background with parent's background color because the visible component
* is smaller than its bounds (for the focus decoration).
*/
public static void paintParentBackground( Graphics g, JComponent c ) {
Container parent = findOpaqueParent( c );
if( parent != null ) {
g.setColor( parent.getBackground() );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
}
/**
* Find the first parent that is opaque.
*/
private static Container findOpaqueParent( Container c ) {
while( (c = c.getParent()) != null ) {
if( c.isOpaque() )
return c;
}
return null;
}
}

View File

@@ -42,6 +42,15 @@ textText=@foreground
window=@background window=@background
#---- Button ----
Button.background=4c5052
Button.startBorderColor=5e6060
Button.endBorderColor=5e6060
Button.disabledBorderColor=5e6060
#---- Label ---- #---- Label ----
Label.disabledForeground=808080 Label.disabledForeground=808080

View File

@@ -16,4 +16,10 @@
#---- UI delegates ---- #---- UI delegates ----
ButtonUI=com.formdev.flatlaf.ui.FlatButtonUI
LabelUI=com.formdev.flatlaf.ui.FlatLabelUI LabelUI=com.formdev.flatlaf.ui.FlatLabelUI
#---- Button ----
Button.border=com.formdev.flatlaf.ui.FlatButtonBorder

View File

@@ -42,6 +42,15 @@ textText=@foreground
window=@background window=@background
#---- Button ----
Button.background=ffffff
Button.startBorderColor=bfbfbf
Button.endBorderColor=b3b3b3
Button.disabledBorderColor=cfcfcf
#---- Label ---- #---- Label ----
Label.disabledForeground=777777 Label.disabledForeground=777777

View File

@@ -50,32 +50,73 @@ public class FlatComponentsTest
JLabel labelLabel = new JLabel(); JLabel labelLabel = new JLabel();
JLabel label1 = new JLabel(); JLabel label1 = new JLabel();
JLabel label2 = new JLabel(); JLabel label2 = new JLabel();
JLabel buttonLabel = new JLabel();
JButton button1 = new JButton();
JButton button2 = new JButton();
JButton button3 = new JButton();
JButton button4 = new JButton();
//======== this ======== //======== this ========
setLayout(new GridBagLayout()); setLayout(new GridBagLayout());
((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0, 0}; ((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0, 0, 0, 0};
((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0}; ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0, 0};
((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 0.0, 1.0E-4}; ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 1.0E-4};
((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0E-4}; ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 0.0, 1.0E-4};
//---- labelLabel ---- //---- labelLabel ----
labelLabel.setText("JLabel:"); labelLabel.setText("JLabel:");
add(labelLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, add(labelLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0)); new Insets(0, 0, 5, 5), 0, 0));
//---- label1 ---- //---- label1 ----
label1.setText("enabled"); label1.setText("enabled");
label1.setDisplayedMnemonic('E'); label1.setDisplayedMnemonic('E');
add(label1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, add(label1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0)); new Insets(0, 0, 5, 5), 0, 0));
//---- label2 ---- //---- label2 ----
label2.setText("disabled"); label2.setText("disabled");
label2.setDisplayedMnemonic('D'); label2.setDisplayedMnemonic('D');
label2.setEnabled(false); label2.setEnabled(false);
add(label2, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, add(label2, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 5, 5), 0, 0));
//---- buttonLabel ----
buttonLabel.setText("JButton:");
add(buttonLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- button1 ----
button1.setText("enabled");
button1.setDisplayedMnemonicIndex(0);
add(button1, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- button2 ----
button2.setText("disabled");
button2.setDisplayedMnemonicIndex(0);
button2.setEnabled(false);
add(button2, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- button3 ----
button3.setText("selected");
button3.setSelected(true);
add(button3, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 5), 0, 0));
//---- button4 ----
button4.setText("selected disabled");
button4.setSelected(true);
button4.setEnabled(false);
add(button4, new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0)); new Insets(0, 0, 0, 0), 0, 0));
// JFormDesigner - End of component initialization //GEN-END:initComponents // JFormDesigner - End of component initialization //GEN-END:initComponents

View File

@@ -7,8 +7,8 @@ new FormModel {
"JavaCodeGenerator.defaultVariableLocal": true "JavaCodeGenerator.defaultVariableLocal": true
} }
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.GridBagLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.GridBagLayout ) {
"$columnSpecs": "0, 0, 0" "$columnSpecs": "0, 0, 0, 0, 0"
"$rowSpecs": "0" "$rowSpecs": "0, 0"
"$hGap": 5 "$hGap": 5
"$vGap": 5 "$vGap": 5
"$alignLeft": true "$alignLeft": true
@@ -34,6 +34,46 @@ new FormModel {
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) { }, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 2 "gridx": 2
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "buttonLabel"
"text": "JButton:"
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridy": 1
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button1"
"text": "enabled"
"displayedMnemonicIndex": 0
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 1
"gridy": 1
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button2"
"text": "disabled"
"displayedMnemonicIndex": 0
"enabled": false
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 2
"gridy": 1
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button3"
"text": "selected"
"selected": true
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 3
"gridy": 1
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button4"
"text": "selected disabled"
"selected": true
"enabled": false
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
"gridx": 4
"gridy": 1
} )
}, 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( 580, 300 ) "size": new java.awt.Dimension( 580, 300 )

View File

@@ -20,6 +20,16 @@
*.foreground=ff0000 *.foreground=ff0000
#---- Button ----
Button.background=ffffff
Button.startBorderColor=ff0000
Button.endBorderColor=0000ff
Button.disabledBorderColor=000088
#---- Label ---- #---- Label ----
Label.foreground=008800
Label.disabledForeground=000088 Label.disabledForeground=000088