OptionPane implementation

This commit is contained in:
Karl Tauber
2019-09-07 10:26:39 +02:00
parent c097775c40
commit 41c4df87ba
7 changed files with 848 additions and 0 deletions

View File

@@ -39,6 +39,7 @@ import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.formdev.flatlaf.ui.FlatEmptyBorder;
import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.util.ScaledNumber;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -254,6 +255,11 @@ public abstract class FlatLaf
if( key.endsWith( "Size" ) && !key.equals( "SplitPane.dividerSize" ))
return parseSize( value );
// scaled number
ScaledNumber scaledNumber = parseScaledNumber( key, value );
if( scaledNumber != null )
return scaledNumber;
// width, height
if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
return parseInteger( value, true );
@@ -359,6 +365,18 @@ public abstract class FlatLaf
return null;
}
private ScaledNumber parseScaledNumber( String key, String value ) {
if( !key.equals( "OptionPane.buttonMinimumWidth" ) )
return null; // not supported
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
System.err.println( "invalid integer '" + value + "'" );
throw ex;
}
}
private static List<String> split( String str, char delim ) {
ArrayList<String> strs = new ArrayList<>();
int delimIndex = str.indexOf( delim );

View File

@@ -0,0 +1,141 @@
/*
* 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.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicOptionPaneUI;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JOptionPane}.
*
* @uiDefault OptionPane.border Border
* @uiDefault OptionPane.messageAreaBorder Border
* @uiDefault OptionPane.buttonAreaBorder Border
* @uiDefault OptionPane.messageForeground Color
* @uiDefault OptionPane.messageFont Font
* @uiDefault OptionPane.buttonFont Font
*
* @uiDefault OptionPane.minimumSize Dimension
* @uiDefault OptionPane.maxCharactersPerLine int
* @uiDefault OptionPane.iconMessageGap int
* @uiDefault OptionPane.messagePadding int
* @uiDefault OptionPane.buttonPadding int
* @uiDefault OptionPane.buttonMinimumWidth int -1=disabled
* @uiDefault OptionPane.sameSizeButtons boolean if true, gives all buttons same size
* @uiDefault OptionPane.setButtonMargin boolean if true, invokes button.setMargin(2,4,2,4)
* @uiDefault OptionPane.buttonOrientation int 0=center, 2=left, 4=right
* @uiDefault OptionPane.isYesLast boolean reverse button order if true
*
* @uiDefault OptionPane.errorIcon Icon
* @uiDefault OptionPane.informationIcon Icon
* @uiDefault OptionPane.questionIcon Icon
* @uiDefault OptionPane.warningIcon Icon
*
* @author Karl Tauber
*/
public class FlatOptionPaneUI
extends BasicOptionPaneUI
{
protected int iconMessageGap;
protected int messagePadding;
protected int maxCharactersPerLine;
private int focusWidth;
public static ComponentUI createUI( JComponent c ) {
return new FlatOptionPaneUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
iconMessageGap = UIManager.getInt( "OptionPane.iconMessageGap" );
messagePadding = UIManager.getInt( "OptionPane.messagePadding" );
maxCharactersPerLine = UIManager.getInt( "OptionPane.maxCharactersPerLine" );
focusWidth = UIManager.getInt( "Component.focusWidth" );
}
@Override
public Dimension getMinimumOptionPaneSize() {
return UIScale.scale( super.getMinimumOptionPaneSize() );
}
@Override
protected int getMaxCharactersPerLineCount() {
int max = super.getMaxCharactersPerLineCount();
return (maxCharactersPerLine > 0 && max == Integer.MAX_VALUE) ? maxCharactersPerLine : max;
}
@Override
protected Container createMessageArea() {
Container messageArea = super.createMessageArea();
// set icon-message gap
if( iconMessageGap > 0 ) {
Component iconMessageSeparator = findByName( messageArea, "OptionPane.separator" );
if( iconMessageSeparator != null )
iconMessageSeparator.setPreferredSize( new Dimension( UIScale.scale( iconMessageGap ), 1 ) );
}
return messageArea;
}
@Override
protected Container createButtonArea() {
Container buttonArea = super.createButtonArea();
// scale button padding and subtract focusWidth
if( buttonArea.getLayout() instanceof ButtonAreaLayout ) {
ButtonAreaLayout layout = (ButtonAreaLayout) buttonArea.getLayout();
layout.setPadding( UIScale.scale( layout.getPadding() - (focusWidth * 2) ) );
}
return buttonArea;
}
@Override
protected void addMessageComponents( Container container, GridBagConstraints cons, Object msg, int maxll,
boolean internallyCreated )
{
// set message padding
if( messagePadding > 0 )
cons.insets.bottom = UIScale.scale( messagePadding );
super.addMessageComponents( container, cons, msg, maxll, internallyCreated );
}
private Component findByName( Container c, String name ) {
for( Component child : c.getComponents() ) {
if( name.equals( child.getName() ) )
return child;
if( child instanceof Container ) {
Component c2 = findByName( (Container) child, name );
if( c2 != null )
return c2;
}
}
return null;
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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 static com.formdev.flatlaf.util.UIScale.scale;
/**
* A number that scales its value.
*
* NOTE:
* Using ScaledNumber in UI defaults works only if the value is get with
* sun.swing.DefaultLookup.getInt(), which is used by some basic UI delegates,
* because this method uses "instanceof Number".
* UIManager.getInt() on the other hand uses "instanceof Integer" and does not work.
*
* @author Karl Tauber
*/
public class ScaledNumber
extends Number
{
private final int value;
public ScaledNumber( int value ) {
this.value = value;
}
@Override
public int intValue() {
return scale( value );
}
@Override
public long longValue() {
return scale( value );
}
@Override
public float floatValue() {
return scale( (float) value );
}
@Override
public double doubleValue() {
return scale( (float) value );
}
@Override
public int hashCode() {
return Integer.hashCode( value );
}
@Override
public boolean equals( Object obj ) {
return (obj instanceof ScaledNumber)
? (value == ((ScaledNumber)obj).value)
: false;
}
@Override
public String toString() {
return Integer.toString( value );
}
}

View File

@@ -27,6 +27,7 @@ ListUI=com.formdev.flatlaf.ui.FlatListUI
MenuUI=com.formdev.flatlaf.ui.FlatMenuUI
MenuBarUI=com.formdev.flatlaf.ui.FlatMenuBarUI
MenuItemUI=com.formdev.flatlaf.ui.FlatMenuItemUI
OptionPaneUI=com.formdev.flatlaf.ui.FlatOptionPaneUI
PasswordFieldUI=com.formdev.flatlaf.ui.FlatPasswordFieldUI
PopupMenuUI=com.formdev.flatlaf.ui.FlatPopupMenuUI
PopupMenuSeparatorUI=com.formdev.flatlaf.ui.FlatPopupMenuSeparatorUI
@@ -130,6 +131,20 @@ MenuItem.arrowIcon=com.formdev.flatlaf.icons.FlatMenuItemArrowIcon
#---- OptionPane ----
OptionPane.border=12,12,12,12
OptionPane.messageAreaBorder=0,0,0,0
OptionPane.buttonAreaBorder=12,0,0,0
OptionPane.messageForeground=null
OptionPane.maxCharactersPerLine=80
OptionPane.iconMessageGap=16
OptionPane.messagePadding=3
OptionPane.buttonPadding=8
OptionPane.buttonMinimumWidth=80
OptionPane.sameSizeButtons=true
OptionPane.setButtonMargin=false
OptionPane.buttonOrientation=4
OptionPane.errorIcon=com.formdev.flatlaf.icons.FlatOptionPaneErrorIcon
OptionPane.informationIcon=com.formdev.flatlaf.icons.FlatOptionPaneInformationIcon
OptionPane.questionIcon=com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon