Compare commits

..

19 Commits
0.21 ... 0.22

Author SHA1 Message Date
Karl Tauber
2399e54a4b release 0.22 2019-12-18 12:28:08 +01:00
Karl Tauber
aea5e8eb16 Demo: bottom horizontal slider bound to the progress bars 2019-12-18 12:21:38 +01:00
Karl Tauber
a3a60c1c4b ProgressBar: reduced thickness from 6 to 4 (as in IntelliJ and Windows 10) 2019-12-18 11:44:34 +01:00
Karl Tauber
c141cb6c6c CheckBox and RadioButton: fixed cut off outer focus border if checkbox/radiobutton border was explicitly set to a EmptyBorder 2019-12-17 23:24:38 +01:00
Karl Tauber
62765ab6ca TextComponent: support placeholder text that is displayed if text field is empty (set client property "JTextField.placeholderText" to a string) 2019-12-17 18:08:45 +01:00
Karl Tauber
e4f7fed523 TextComponent: scale caret width on HiDPI screens when running on Java 8 2019-12-17 17:34:54 +01:00
Karl Tauber
bf8cc268cc on Mac show mnemonics only when Ctrl and Alt keys are pressed (issue #4) 2019-12-17 11:35:16 +01:00
Karl Tauber
8450e74832 TabbedPane: support separators between tabs (TabbedPane.showTabSeparators) 2019-12-16 20:40:29 +01:00
Karl Tauber
475b258e4a Button: enabled Button.defaultButtonFollowsFocus on Windows, which allows pressing focused button with <kbd>Enter</kbd> key (as in Windows LaF) 2019-12-16 18:11:48 +01:00
Karl Tauber
f20803ae57 ProgressBar: If progress text is visible:
- use smaller font
  - reduced height
  - changed style to rounded rectangle
  - fixed painting issues on low values

Support configure of arc with `ProgressBar.arc`
2019-12-16 17:39:46 +01:00
Karl Tauber
3fcb17931a fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is zero (default in "Flat Light" and "Flat Dark" themes) 2019-12-15 11:36:24 +01:00
Karl Tauber
736c7b8377 CheckBox: changed CheckBox.arc from radius to diameter to be consistent with Button.arc and Component.arc 2019-12-14 23:36:22 +01:00
Karl Tauber
05743e2d8b FlatUIUtils: renamed and documented component painting methods 2019-12-14 23:17:11 +01:00
Karl Tauber
6cd2c7f26d InternalFrame: test application implemented (issue #11) 2019-12-14 11:57:07 +01:00
Karl Tauber
469e5bd179 ToggleButton: removed "ToggleButton.arc" because it was only used for the background, but not for the border, which is painted in FlatButtonBorder 2019-12-14 00:05:47 +01:00
Karl Tauber
dbeb3f04e7 UI inspector:
- fixed wrong detection of components under mouse location if window contains a menubar
- fixed positioning of tooltip in bottom and right window area to avoid that the tooltip overlaps the inspected component
2019-12-13 23:49:49 +01:00
Karl Tauber
e9b17ac24a UI inspector: support using it in any application 2019-12-13 23:24:10 +01:00
Karl Tauber
65fbcedaa4 TabbedPane: support background color for selected tabs 2019-12-13 23:14:41 +01:00
Karl Tauber
c4183ada11 ScrollPane and FlatSpinner: made getHandler() methods private 2019-12-11 21:58:39 +01:00
45 changed files with 1098 additions and 211 deletions

View File

@@ -1,6 +1,31 @@
FlatLaf Change Log
==================
## 0.22
- TextComponent: Support placeholder text that is displayed if text field is
empty (set client property "JTextField.placeholderText" to a string).
- TextComponent: Scale caret width on HiDPI screens when running on Java 8.
- ProgressBar: If progress text is visible:
- use smaller font
- reduced height
- changed style to rounded rectangle
- fixed painting issues on low values
- ProgressBar: Support configure of arc with `ProgressBar.arc`.
- ProgressBar: Reduced thickness from 6 to 4.
- TabbedPane: Support background color for selected tabs
(`TabbedPane.selectedBackground`) and separators between tabs
(`TabbedPane.showTabSeparators`).
- CheckBox: changed `CheckBox.arc` from radius to diameter to be consistent with
`Button.arc` and `Component.arc`
- Button: Enabled `Button.defaultButtonFollowsFocus` on Windows, which allows
pressing focused button with <kbd>Enter</kbd> key (as in Windows LaF).
- Fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is
zero (default in "Flat Light" and "Flat Dark" themes).
- On Mac show mnemonics only when <kbd>Ctrl</kbd> and <kbd>Alt</kbd> keys are
pressed. (issue #4)
## 0.21
- ScrollBar: Show decrease/increase arrow buttons if client property

View File

@@ -45,7 +45,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf
version: 0.21
version: 0.22
Otherwise download `flatlaf-<version>.jar` here:

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
version = "0.21"
version = "0.22"
allprojects {
repositories {

View File

@@ -64,6 +64,14 @@ public interface FlatClientProperties
*/
String SCROLL_BAR_SHOW_BUTTONS = "JScrollBar.showButtons";
/**
* Specifies whether separators are shown between tabs.
* <p>
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
* <strong>Value type</strong> {@link java.lang.Boolean}
*/
String TABBED_PANE_SHOW_TAB_SEPARATORS = "JTabbedPane.showTabSeparators";
/**
* Specifies whether a full border is painted around a tabbed pane.
* <p>
@@ -72,10 +80,27 @@ public interface FlatClientProperties
*/
String TABBED_PANE_HAS_FULL_BORDER = "JTabbedPane.hasFullBorder";
/**
* Placeholder text that is only painted if the text field is empty.
* <p>
* <strong>Component</strong> {@link javax.swing.JTextField} or {@link javax.swing.JComboBox}<br>
* <strong>Value type</strong> {@link java.lang.String}
*/
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
/**
* Checks whether a client property of a component has the given value.
*/
static boolean clientPropertyEquals( JComponent c, String key, Object value ) {
return Objects.equals( c.getClientProperty( key ), value );
}
/**
* Checks whether a client property of a component is a boolean and returns its value.
* If the client property is not set, or not a boolean, defaultValue is returned.
*/
static boolean clientPropertyBoolean( JComponent c, String key, boolean defaultValue ) {
Object value = c.getClientProperty( key );
return (value instanceof Boolean) ? (boolean) value : defaultValue;
}
}

View File

@@ -61,7 +61,7 @@ public abstract class FlatLaf
private PropertyChangeListener desktopPropertyListener;
private KeyEventPostProcessor mnemonicListener;
private static boolean altKeyPressed;
private static boolean showMnemonics;
private Consumer<UIDefaults> postInitialization;
@@ -113,8 +113,7 @@ public abstract class FlatLaf
// add mnemonic listener
mnemonicListener = e -> {
if( e.getKeyCode() == KeyEvent.VK_ALT )
altKeyChanged( e.getID() == KeyEvent.KEY_PRESSED );
checkShowMnemonics( e );
return false;
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( mnemonicListener );
@@ -283,6 +282,9 @@ public abstract class FlatLaf
defaults.put( key, uiFont );
}
defaults.put( "MenuItem.acceleratorFont", uiFont );
// use smaller font for progress bar
defaults.put( "ProgressBar.font", UIScale.scaleFont( uiFont, 0.85f ) );
}
/**
@@ -354,14 +356,27 @@ public abstract class FlatLaf
}
public static boolean isShowMnemonics() {
return altKeyPressed || !UIManager.getBoolean( "Component.hideMnemonics" );
return showMnemonics || !UIManager.getBoolean( "Component.hideMnemonics" );
}
private static void altKeyChanged( boolean pressed ) {
if( pressed == altKeyPressed )
private static void checkShowMnemonics( KeyEvent e ) {
int keyCode = e.getKeyCode();
if( SystemInfo.IS_MAC ) {
// Ctrl+Alt keys must be pressed on Mac
if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT )
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED && e.isControlDown() && e.isAltDown() );
} else {
// Alt key must be pressed on Windows and Linux
if( keyCode == KeyEvent.VK_ALT )
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED );
}
}
private static void showMnemonics( boolean show ) {
if( show == showMnemonics )
return;
altKeyPressed = pressed;
showMnemonics = show;
// check whether it is necessary to repaint
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )

View File

@@ -31,6 +31,7 @@ import java.util.Properties;
import java.util.ServiceLoader;
import java.util.function.Function;
import javax.swing.UIDefaults;
import javax.swing.UIDefaults.ActiveValue;
import javax.swing.UIDefaults.LazyValue;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.DimensionUIResource;
@@ -39,9 +40,9 @@ 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;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
/**
* Load UI defaults from properties files associated to Flat LaF classes and add to UI defaults.
@@ -202,7 +203,7 @@ class UIDefaultsLoader
return resolveValue( properties, newValue );
}
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDNUMBER, INSTANCE, CLASS }
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDINTEGER, INSTANCE, CLASS }
static Object parseValue( String key, String value ) {
return parseValue( key, value, v -> v, Collections.emptyList() );
@@ -266,7 +267,7 @@ class UIDefaultsLoader
case INSETS: return parseInsets( value );
case SIZE: return parseSize( value );
case COLOR: return parseColorOrFunction( value, true );
case SCALEDNUMBER: return parseScaledNumber( value );
case SCALEDINTEGER: return parseScaledInteger( value );
case INSTANCE: return parseInstance( value, addonClassLoaders );
case CLASS: return parseClass( value, addonClassLoaders );
case UNKNOWN:
@@ -506,11 +507,10 @@ class UIDefaultsLoader
return null;
}
private static ScaledNumber parseScaledNumber( String value ) {
try {
return new ScaledNumber( Integer.parseInt( value ) );
} catch( NumberFormatException ex ) {
throw new NumberFormatException( "invalid integer '" + value + "'" );
}
private static ActiveValue parseScaledInteger( String value ) {
int val = parseInteger( value, true );
return (ActiveValue) t -> {
return UIScale.scale( val );
};
}
}

View File

@@ -62,7 +62,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatCheckBoxIcon
extends FlatAbstractIcon
{
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
public final int focusWidth = UIManager.getInt( "Component.focusWidth" );
protected final Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusedColor",
UIManager.getColor( "Component.focusColor" ) );
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
@@ -133,17 +133,17 @@ public class FlatCheckBoxIcon
protected void paintFocusBorder( Graphics2D g2 ) {
// the outline focus border is painted outside of the icon
int wh = ICON_SIZE - 1 + (focusWidth * 2);
int arcwh = (arc + focusWidth) * 2;
int arcwh = arc + (focusWidth * 2);
g2.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
}
protected void paintBorder( Graphics2D g2 ) {
int arcwh = arc * 2;
int arcwh = arc;
g2.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
}
protected void paintBackground( Graphics2D g2 ) {
int arcwh = (arc * 2) - 1;
int arcwh = arc - 1;
g2.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
}

View File

@@ -79,12 +79,12 @@ public class FlatBorder
if( isFocused( c ) ) {
g2.setColor( getFocusColor( c ) );
FlatUIUtils.paintOutlineBorder( g2, x, y, width, height, focusWidth,
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height, focusWidth,
getLineWidth() + scale( (float) innerFocusWidth ), arc );
}
g2.setPaint( getBorderColor( c ) );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, borderWidth, arc );
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
} finally {
g2.dispose();
}

View File

@@ -134,7 +134,7 @@ public class FlatButtonUI
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
arc = UIManager.getInt( prefix + "arc" );
arc = UIManager.getInt( "Button.arc" );
minimumWidth = UIManager.getInt( prefix + "minimumWidth" );
iconTextGap = FlatUIUtils.getUIInt( prefix + "iconTextGap", 4 );
@@ -251,7 +251,7 @@ public class FlatButtonUI
g2.setPaint( new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg ) );
else
FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();
}

View File

@@ -52,6 +52,7 @@ import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -239,7 +240,8 @@ public class FlatComboBoxUI
} else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) {
ComponentOrientation o = (ComponentOrientation) e.getNewValue();
editor.applyComponentOrientation( o );
}
} else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) )
editor.repaint();
}
};
}
@@ -316,7 +318,7 @@ public class FlatComboBoxUI
g2.setColor( enabled
? (editableBackground != null && comboBox.isEditable() ? editableBackground : c.getBackground())
: getDisabledBackground( comboBox ) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
@@ -326,7 +328,7 @@ public class FlatComboBoxUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -335,7 +337,7 @@ public class FlatComboBoxUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
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 - 1 - (focusWidth * 2)) );
}
paint( g, c );

View File

@@ -39,8 +39,10 @@ import javax.swing.plaf.ComponentUI;
*
* <!-- FlatTextFieldUI -->
*
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault FormattedTextField.placeholderForeground Color
*
* @author Karl Tauber
*/

View File

@@ -48,7 +48,7 @@ public class FlatLineBorder
try {
FlatUIUtils.setRenderingHints( g2 );
g2.setColor( lineColor );
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, 0f, scale( 1f ), 0f );
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( 1f ), 0f );
} finally {
g2.dispose();
}

View File

@@ -17,14 +17,17 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -51,6 +54,7 @@ import com.formdev.flatlaf.util.SystemInfo;
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault PasswordField.placeholderForeground Color
*
* @author Karl Tauber
*/
@@ -60,6 +64,7 @@ public class FlatPasswordFieldUI
protected int focusWidth;
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color placeholderForeground;
private FocusListener focusListener;
@@ -75,9 +80,11 @@ public class FlatPasswordFieldUI
if( SystemInfo.IS_MAC )
LookAndFeel.installProperty( getComponent(), "echoChar", '\u2022' );
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
@@ -88,6 +95,8 @@ public class FlatPasswordFieldUI
protected void uninstallDefaults() {
super.uninstallDefaults();
placeholderForeground = null;
MigLayoutVisualPadding.uninstall( getComponent() );
}
@@ -107,9 +116,18 @@ public class FlatPasswordFieldUI
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
getComponent().repaint();
}
@Override
protected void paintSafely( Graphics g ) {
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
super.paintSafely( g );
}

View File

@@ -17,13 +17,16 @@
package com.formdev.flatlaf.ui;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JProgressBar;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI;
import com.formdev.flatlaf.util.UIScale;
@@ -44,11 +47,19 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault ProgressBar.repaintInterval int default is 50 milliseconds
* @uiDefault ProgressBar.cycleTime int default is 3000 milliseconds
*
* <!-- FlatProgressBarUI -->
*
* @uiDefault ProgressBar.arc int
*
* @author Karl Tauber
*/
public class FlatProgressBarUI
extends BasicProgressBarUI
{
protected int arc;
protected Dimension horizontalSize;
protected Dimension verticalSize;
public static ComponentUI createUI( JComponent c ) {
return new FlatProgressBarUI();
}
@@ -58,16 +69,37 @@ public class FlatProgressBarUI
super.installDefaults();
LookAndFeel.installProperty( progressBar, "opaque", false );
arc = UIManager.getInt( "ProgressBar.arc" );
horizontalSize = UIManager.getDimension( "ProgressBar.horizontalSize" );
verticalSize = UIManager.getDimension( "ProgressBar.verticalSize" );
}
@Override
public Dimension getPreferredSize( JComponent c ) {
Dimension size = super.getPreferredSize( c );
if( progressBar.isStringPainted() ) {
// recalculate progress height/width to make it smaller
Insets insets = progressBar.getInsets();
FontMetrics fm = progressBar.getFontMetrics( progressBar.getFont() );
if( progressBar.getOrientation() == JProgressBar.HORIZONTAL )
size.height = Math.max( fm.getHeight() + insets.top + insets.bottom, getPreferredInnerHorizontal().height );
else
size.width = Math.max( fm.getHeight() + insets.left + insets.right, getPreferredInnerVertical().width );
}
return size;
}
@Override
protected Dimension getPreferredInnerHorizontal() {
return UIScale.scale( super.getPreferredInnerHorizontal() );
return UIScale.scale( horizontalSize );
}
@Override
protected Dimension getPreferredInnerVertical() {
return UIScale.scale( super.getPreferredInnerVertical() );
return UIScale.scale( verticalSize );
}
@Override
@@ -90,13 +122,14 @@ public class FlatProgressBarUI
return;
boolean horizontal = (progressBar.getOrientation() == JProgressBar.HORIZONTAL);
int arc = horizontal ? height : width;
int arc = Math.min( UIScale.scale( this.arc ), horizontal ? height : width );
FlatUIUtils.setRenderingHints( (Graphics2D) g );
// paint track
RoundRectangle2D.Float trackShape = new RoundRectangle2D.Float( x, y, width, height, arc, arc );
g.setColor( progressBar.getBackground() );
((Graphics2D)g).fill( new RoundRectangle2D.Float( x, y, width, height, arc, arc ) );
((Graphics2D)g).fill( trackShape );
// paint progress
if( progressBar.isIndeterminate() ) {
@@ -112,11 +145,19 @@ public class FlatProgressBarUI
} else {
int amountFull = getAmountFull( insets, width, height );
g.setColor( progressBar.getForeground() );
((Graphics2D)g).fill( horizontal
RoundRectangle2D.Float progressShape = horizontal
? new RoundRectangle2D.Float( c.getComponentOrientation().isLeftToRight() ? x : x + (width - amountFull),
y, amountFull, height, arc, arc )
: new RoundRectangle2D.Float( x, y + (height - amountFull), width, amountFull, arc, arc ) );
: new RoundRectangle2D.Float( x, y + (height - amountFull), width, amountFull, arc, arc );
g.setColor( progressBar.getForeground() );
if( amountFull < (horizontal ? height : width) ) {
// special painting for low amounts to avoid painting outside of track
Area area = new Area( trackShape );
area.intersect( new Area( progressShape ) );
((Graphics2D)g).fill( area );
} else
((Graphics2D)g).fill( progressShape );
if( progressBar.isStringPainted() )
paintString( g, x, y, width, height, amountFull, insets );

View File

@@ -18,7 +18,9 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.CellRendererPane;
@@ -28,6 +30,8 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JRadioButton}.
@@ -92,6 +96,26 @@ public class FlatRadioButtonUI
defaults_initialized = false;
}
private static Insets tempInsets = new Insets( 0, 0, 0, 0 );
@Override
public Dimension getPreferredSize( JComponent c ) {
Dimension size = super.getPreferredSize( c );
// small insets fix
int focusWidth = getIconFocusWidth( c );
if( focusWidth > 0 ) {
// Increase preferred width and height if insets were explicitly reduced (e.g. with
// an EmptyBorder) and icon has a focus width, which is not included in icon size.
// Otherwise the component may be too small and outer focus border may be cut off.
Insets insets = c.getInsets( tempInsets );
size.width += Math.max( focusWidth - insets.left, 0 ) + Math.max( focusWidth - insets.right, 0 );
size.height += Math.max( focusWidth - insets.top, 0 ) + Math.max( focusWidth - insets.bottom, 0 );
}
return size;
}
@Override
public void paint( Graphics g, JComponent c ) {
// fill background even if opaque if
@@ -104,6 +128,29 @@ public class FlatRadioButtonUI
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
// small insets fix
int focusWidth = getIconFocusWidth( c );
if( focusWidth > 0 ) {
boolean ltr = c.getComponentOrientation().isLeftToRight();
Insets insets = c.getInsets( tempInsets );
int leftOrRightInset = ltr ? insets.left : insets.right;
if( focusWidth > leftOrRightInset ) {
// The left (or right) inset is smaller than the focus width, which may be
// the case if insets were explicitly reduced (e.g. with an EmptyBorder).
// In this case the width has been increased in getPreferredSize() and
// here it is necessary to fix icon and text painting location.
int offset = focusWidth - leftOrRightInset;
if( !ltr )
offset = -offset;
// move the graphics origin to the left (or right)
g.translate( offset, 0 );
super.paint( g, c );
g.translate( -offset, 0 );
return;
}
}
super.paint( g, c );
}
@@ -111,4 +158,11 @@ public class FlatRadioButtonUI
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
FlatButtonUI.paintText( g, b, textRect, text, b.isEnabled() ? b.getForeground() : disabledText );
}
private int getIconFocusWidth( JComponent c ) {
AbstractButton b = (AbstractButton) c;
return (b.getIcon() == null && getDefaultIcon() instanceof FlatCheckBoxIcon)
? UIScale.scale( ((FlatCheckBoxIcon)getDefaultIcon()).focusWidth )
: 0;
}
}

View File

@@ -113,7 +113,7 @@ public class FlatScrollPaneUI
};
}
public Handler getHandler() {
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;

View File

@@ -159,7 +159,7 @@ public class FlatSpinnerUI
handler = null;
}
public Handler getHandler() {
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
@@ -267,7 +267,7 @@ public class FlatSpinnerUI
g2.setColor( enabled
? c.getBackground()
: (isIntelliJTheme ? FlatUIUtils.getParentBackground( c ) : disabledBackground) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow buttons background
if( enabled ) {
@@ -277,7 +277,7 @@ public class FlatSpinnerUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -285,7 +285,7 @@ public class FlatSpinnerUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
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 - 1 - (focusWidth * 2) ) );
paint( g, c );
}

View File

@@ -41,6 +41,7 @@ import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.text.View;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTabbedPane}.
@@ -53,11 +54,13 @@ import com.formdev.flatlaf.FlatLaf;
* @uiDefault TabbedPane.foreground Color
* @uiDefault TabbedPane.shadow Color used for scroll arrows and cropped line
* @uiDefault TabbedPane.disabledForeground Color
* @uiDefault TabbedPane.selectedBackground Color optional
* @uiDefault TabbedPane.selectedForeground Color
* @uiDefault TabbedPane.underlineColor Color
* @uiDefault TabbedPane.disabledUnderlineColor Color
* @uiDefault TabbedPane.hoverColor Color
* @uiDefault TabbedPane.focusColor Color
* @uiDefault TabbedPane.tabSeparatorColor Color optional; defaults to TabbedPane.contentAreaColor
* @uiDefault TabbedPane.contentAreaColor Color
* @uiDefault TabbedPane.textIconGap int
* @uiDefault TabbedPane.tabInsets Insets
@@ -65,6 +68,7 @@ import com.formdev.flatlaf.FlatLaf;
* @uiDefault TabbedPane.tabHeight int
* @uiDefault TabbedPane.tabSelectionHeight int
* @uiDefault TabbedPane.contentSeparatorHeight int
* @uiDefault TabbedPane.showTabSeparators boolean
* @uiDefault TabbedPane.hasFullBorder boolean
*
* @author Karl Tauber
@@ -73,16 +77,19 @@ public class FlatTabbedPaneUI
extends BasicTabbedPaneUI
{
protected Color disabledForeground;
protected Color selectedBackground;
protected Color selectedForeground;
protected Color underlineColor;
protected Color disabledUnderlineColor;
protected Color hoverColor;
protected Color focusColor;
protected Color tabSeparatorColor;
protected Color contentAreaColor;
protected int tabHeight;
protected int tabSelectionHeight;
protected int contentSeparatorHeight;
protected boolean showTabSeparators;
protected boolean hasFullBorder;
protected boolean tabsOverlapBorder;
@@ -95,16 +102,19 @@ public class FlatTabbedPaneUI
super.installDefaults();
disabledForeground = UIManager.getColor( "TabbedPane.disabledForeground" );
selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" );
selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" );
underlineColor = UIManager.getColor( "TabbedPane.underlineColor" );
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" );
@@ -124,11 +134,13 @@ public class FlatTabbedPaneUI
super.uninstallDefaults();
disabledForeground = null;
selectedBackground = null;
selectedForeground = null;
underlineColor = null;
disabledUnderlineColor = null;
hoverColor = null;
focusColor = null;
tabSeparatorColor = null;
contentAreaColor = null;
MigLayoutVisualPadding.uninstall( tabPane );
@@ -141,9 +153,12 @@ public class FlatTabbedPaneUI
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( TABBED_PANE_HAS_FULL_BORDER.equals( e.getPropertyName() ) ) {
tabPane.revalidate();
tabPane.repaint();
switch( e.getPropertyName() ) {
case TABBED_PANE_SHOW_TAB_SEPARATORS:
case TABBED_PANE_HAS_FULL_BORDER:
tabPane.revalidate();
tabPane.repaint();
break;
}
}
};
@@ -197,7 +212,7 @@ public class FlatTabbedPaneUI
*/
@Override
protected Insets getContentBorderInsets( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
@@ -262,7 +277,9 @@ public class FlatTabbedPaneUI
? hoverColor
: (enabled && isSelected && tabPane.hasFocus()
? focusColor
: tabPane.getBackgroundAt( tabIndex )) );
: (selectedBackground != null && enabled && isSelected
? selectedBackground
: tabPane.getBackgroundAt( tabIndex ))) );
g.fillRect( x, y, w, h );
}
@@ -270,6 +287,26 @@ public class FlatTabbedPaneUI
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected )
{
// paint tab separators
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
!isLastInRun( tabIndex ) )
{
float sepWidth = UIScale.scale( 1f );
float offset = UIScale.scale( 5f );
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
if( tabPlacement == LEFT || tabPlacement == RIGHT ) {
// paint tab separator at bottom side
((Graphics2D)g).fill( new Rectangle2D.Float( x + offset, y + h - sepWidth, w - (offset * 2), sepWidth ) );
} else if( tabPane.getComponentOrientation().isLeftToRight() ) {
// paint tab separator at right side
((Graphics2D)g).fill( new Rectangle2D.Float( x + w - sepWidth, y + offset, sepWidth, h - (offset * 2) ) );
} else {
// paint tab separator at left side
((Graphics2D)g).fill( new Rectangle2D.Float( x, y + offset, sepWidth, h - (offset * 2) ) );
}
}
if( isSelected )
paintTabSelection( g, tabPlacement, x, y, w, h );
}
@@ -334,7 +371,7 @@ public class FlatTabbedPaneUI
}
/**
* Actually does the nearly the same as super.paintContentBorder() but
* Actually does nearly the same as super.paintContentBorder() but
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
* - not invoking paintContentBorder*Edge() methods
* - repaint selection
@@ -379,7 +416,7 @@ public class FlatTabbedPaneUI
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
@@ -414,6 +451,11 @@ public class FlatTabbedPaneUI
{
}
private boolean isLastInRun( int tabIndex ) {
int run = getRunForTab( tabPane.getTabCount(), tabIndex );
return lastTabInRun( tabPane.getTabCount(), run ) == tabIndex;
}
private boolean isScrollTabLayout() {
return tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
}

View File

@@ -20,9 +20,12 @@ import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JSpinner;
@@ -33,6 +36,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextFieldUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
@@ -57,6 +61,7 @@ import javax.swing.text.JTextComponent;
* @uiDefault Component.focusWidth int
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextField.placeholderForeground Color
*
* @author Karl Tauber
*/
@@ -66,6 +71,7 @@ public class FlatTextFieldUI
protected int focusWidth;
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color placeholderForeground;
private FocusListener focusListener;
@@ -77,9 +83,11 @@ public class FlatTextFieldUI
protected void installDefaults() {
super.installDefaults();
String prefix = getPropertyPrefix();
focusWidth = UIManager.getInt( "Component.focusWidth" );
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
@@ -90,6 +98,8 @@ public class FlatTextFieldUI
protected void uninstallDefaults() {
super.uninstallDefaults();
placeholderForeground = null;
MigLayoutVisualPadding.uninstall( getComponent() );
}
@@ -109,9 +119,18 @@ public class FlatTextFieldUI
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) )
getComponent().repaint();
}
@Override
protected void paintSafely( Graphics g ) {
paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
paintPlaceholder( g, getComponent(), placeholderForeground );
super.paintSafely( g );
}
@@ -146,12 +165,37 @@ public class FlatTextFieldUI
: (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())
? FlatUIUtils.getParentBackground( c )
: background) );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
} finally {
g2.dispose();
}
}
static void paintPlaceholder( Graphics g, JTextComponent c, Color placeholderForeground ) {
// check whether text component is empty
if( c.getDocument().getLength() > 0 )
return;
// check for JComboBox
Container parent = c.getParent();
JComponent jc = (parent instanceof JComboBox) ? (JComboBox<?>) parent : c;
// get placeholder text
Object placeholder = jc.getClientProperty( FlatClientProperties.PLACEHOLDER_TEXT );
if( !(placeholder instanceof String) )
return;
// compute placeholder location
Insets insets = c.getInsets();
FontMetrics fm = c.getFontMetrics( c.getFont() );
int x = insets.left;
int y = insets.top + fm.getAscent() + ((c.getHeight() - insets.top - insets.bottom - fm.getHeight()) / 2);
// paint placeholder
g.setColor( placeholderForeground );
FlatUIUtils.drawString( c, g, (String) placeholder, x, y );
}
@Override
public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( super.getPreferredSize( c ), c );

View File

@@ -38,7 +38,7 @@ import javax.swing.plaf.ComponentUI;
* <!-- FlatButtonUI -->
*
* @uiDefault Component.focusWidth int
* @uiDefault ToggleButton.arc int
* @uiDefault Button.arc int
* @uiDefault ToggleButton.minimumWidth int
* @uiDefault ToggleButton.iconTextGap int
* @uiDefault ToggleButton.startBackground Color optional; if set, a gradient paint is used and ToggleButton.background is ignored

View File

@@ -39,6 +39,7 @@ import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.UIScale;
@@ -125,9 +126,73 @@ public class FlatUIUtils
}
/**
* Draws a round rectangle.
* Paints an outer border, which is usually a focus border.
* <p>
* The outside bounds of the painted border are {@code x,y,width,height}.
* The line width of the painted border is {@code focusWidth + lineWidth}.
* The given arc diameter refers to the inner rectangle ({@code x,y,width,height} minus {@code focusWidth}).
*
* @see #paintComponentBorder
* @see #paintComponentBackground
*/
public static void drawRoundRectangle( Graphics2D g, int x, int y, int width, int height,
public static void paintComponentOuterBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentOuterBorderImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentOuterBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
}
private static void paintComponentOuterBorderImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float outerRadius = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
float ow = focusWidth + lineWidth;
float innerRadius = outerRadius - ow;
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createRoundRectanglePath( x, y, width, height, outerRadius, outerRadius, outerRadius, outerRadius ), false );
path.append( createRoundRectanglePath( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerRadius, innerRadius, innerRadius, innerRadius ), false );
g.fill( path );
}
/**
* Draws the border of a component as round rectangle.
* <p>
* The outside bounds of the painted border are
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
*
* @see #paintComponentOuterBorder
* @see #paintComponentBackground
*/
public static void paintComponentBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentBorderImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
}
private static void paintComponentBorderImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
@@ -146,9 +211,33 @@ public class FlatUIUtils
}
/**
* Fills a round rectangle.
* Fills the background of a component with a round rectangle.
* <p>
* The bounds of the painted round rectangle are
* {@code x + focusWidth, y + focusWidth, width - (focusWidth * 2), height - (focusWidth * 2)}.
* The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}).
*
* @see #paintComponentOuterBorder
* @see #paintComponentBorder
*/
public static void fillRoundRectangle( Graphics2D g, int x, int y, int width, int height,
public static void paintComponentBackground( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float arc )
{
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
(g2d, x2, y2, width2, height2, scaleFactor) -> {
paintComponentBackgroundImpl( g2d, x2, y2, width2, height2,
(float) (focusWidth * scaleFactor), (float) (arc * scaleFactor) );
} );
return;
}
paintComponentBackgroundImpl( g, x, y, width, height, focusWidth, arc );
}
private static void paintComponentBackgroundImpl( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float arc )
{
g.fill( new RoundRectangle2D.Float(
@@ -189,25 +278,6 @@ public class FlatUIUtils
return null;
}
/**
* Paints an outline border.
*/
public static void paintOutlineBorder( Graphics2D g, int x, int y, int width, int height,
float focusWidth, float lineWidth, float arc )
{
float outerArc = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
float ow = focusWidth + lineWidth;
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createOutlinePath( x, y, width, height, outerArc ), false );
path.append( createOutlinePath( x + ow, y + ow, width - (ow * 2), height - (ow * 2), outerArc - ow ), false );
g.fill( path );
}
private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) {
return createRoundRectanglePath( x, y, width, height, arc, arc, arc, arc );
}
/**
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
*/
@@ -222,7 +292,7 @@ public class FlatUIUtils
}
/**
* Creates a filled rounded rectangle shape and allows specifying the radius or each corner.
* Creates a filled rounded rectangle shape and allows specifying the radius of each corner.
*/
public static Shape createRoundRectanglePath( float x, float y, float width, float height,
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
@@ -256,10 +326,16 @@ public class FlatUIUtils
return rect;
}
/**
* Creates a closed path for the given points.
*/
public static Path2D createPath( double... points ) {
return createPath( true, points );
}
/**
* Creates a open or closed path for the given points.
*/
public static Path2D createPath( boolean close, double... points ) {
Path2D path = new Path2D.Float();
path.moveTo( points[0], points[1] );

View File

@@ -0,0 +1,111 @@
/*
* 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.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
/**
* @author Karl Tauber
*/
public class HiDPIUtils
{
public interface Painter {
public void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
}
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
paintAtScale1x( g, 0, 0, c.getWidth(), c.getHeight(), painter );
}
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) {
paintAtScale1x( g, x, y, width, height, UIScale.getSystemScaleFactor( g ), painter );
}
/**
* Paint at system scale factor 1x to avoid rounding issues at 125%, 150% and 175% scaling.
* <p>
* Scales the given Graphics2D down to 100% and invokes the
* given painter passing scaled x, y, width and height.
* <p>
* Uses the same scaling calculation as the JRE uses.
*/
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height,
double scaleFactor, Painter painter )
{
if( scaleFactor == 1 ) {
painter.paint( g, x, y, width, height, 1 );
return;
}
// save original transform
AffineTransform transform = g.getTransform();
// scale rectangle
Rectangle2D.Double scaledRect = scale( transform, x, y, width, height );
try {
// unscale to factor 1.0
double scale = 1.0 / scaleFactor;
g.scale( scale, scale );
// compute origin delta x/y
double dx = Math.floor( scaledRect.x ) - transform.getTranslateX();
double dy = Math.floor( scaledRect.y ) - transform.getTranslateY();
// move origin to make sure that origin x/y are at whole numbers
if( dx != 0 || dy != 0 )
g.translate( dx, dy );
int swidth = (int) scaledRect.width;
int sheight = (int) scaledRect.height;
// paint
painter.paint( g, 0, 0, swidth, sheight, scaleFactor );
} finally {
// restore original transform
g.setTransform( transform );
}
}
/**
* Scales a rectangle in the same way as the JRE does in
* sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(),
* which is used by Graphics.fillRect().
*/
private static Rectangle2D.Double scale( AffineTransform transform, int x, int y, int width, int height ) {
double dx1 = transform.getScaleX();
double dy2 = transform.getScaleY();
double px = x * dx1 + transform.getTranslateX();
double py = y * dy2 + transform.getTranslateY();
dx1 *= width;
dy2 *= height;
double newx = normalize( px );
double newy = normalize( py );
dx1 = normalize( px + dx1 ) - newx;
dy2 = normalize( py + dy2 ) - newy;
return new Rectangle2D.Double( newx, newy, dx1, dy2 );
}
private static double normalize( double value ) {
return Math.floor( value + 0.25 ) + 0.25;
}
}

View File

@@ -1,77 +0,0 @@
/*
* 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

@@ -197,6 +197,14 @@ public class UIScale
return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize );
}
/**
* Scales the given font.
*/
public static FontUIResource scaleFont( FontUIResource font, float scaleFactor ) {
int newFontSize = Math.round( font.getSize() * scaleFactor );
return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize );
}
/**
* Similar to sun.java2d.SunGraphicsEnvironment.getScaleFactor(String)
*/

View File

@@ -94,15 +94,21 @@ Button.margin=2,14,2,14
Button.iconTextGap=4
Button.rollover=true
Button.defaultButtonFollowsFocus=false
[win]Button.defaultButtonFollowsFocus=true
Button.default.borderWidth=1
#---- Caret ----
Caret.width={scaledInteger}1
#---- CheckBox ----
CheckBox.border=com.formdev.flatlaf.ui.FlatMarginBorder
CheckBox.icon=com.formdev.flatlaf.icons.FlatCheckBoxIcon
CheckBox.arc=2
CheckBox.arc=4
CheckBox.margin=2,2,2,2
CheckBox.iconTextGap=4
CheckBox.rollover=true
@@ -141,8 +147,8 @@ Component.hideMnemonics=true
#---- EditorPane ----
EditorPane.border=com.formdev.flatlaf.ui.FlatMarginBorder
EditorPane.background=@textComponentBackground
EditorPane.margin=@textComponentMargin
EditorPane.background=@textComponentBackground
#---- FileChooser ----
@@ -166,8 +172,9 @@ FileView.floppyDriveIcon=com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon
#---- FormattedTextField ----
FormattedTextField.border=com.formdev.flatlaf.ui.FlatBorder
FormattedTextField.background=@textComponentBackground
FormattedTextField.margin=@textComponentMargin
FormattedTextField.background=@textComponentBackground
FormattedTextField.placeholderForeground=@disabledText
#---- HelpButton ----
@@ -226,7 +233,7 @@ OptionPane.maxCharactersPerLine=80
OptionPane.iconMessageGap=16
OptionPane.messagePadding=3
OptionPane.buttonPadding=8
OptionPane.buttonMinimumWidth={scaledNumber}72
OptionPane.buttonMinimumWidth={scaledInteger}72
OptionPane.sameSizeButtons=true
OptionPane.setButtonMargin=false
OptionPane.buttonOrientation=4
@@ -241,8 +248,9 @@ OptionPane.warningIcon=com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon
#---- PasswordField ----
PasswordField.border=com.formdev.flatlaf.ui.FlatBorder
PasswordField.background=@textComponentBackground
PasswordField.margin=@textComponentMargin
PasswordField.background=@textComponentBackground
PasswordField.placeholderForeground=@disabledText
#---- PopupMenu ----
@@ -261,8 +269,9 @@ PopupMenuSeparator.stripeIndent=4
#---- ProgressBar ----
ProgressBar.border=com.formdev.flatlaf.ui.FlatEmptyBorder
ProgressBar.horizontalSize=146,6
ProgressBar.verticalSize=6,146
ProgressBar.arc=4
ProgressBar.horizontalSize=146,4
ProgressBar.verticalSize=4,146
#---- RadioButton ----
@@ -331,8 +340,8 @@ SplitPane.dividerSize={integer}5
SplitPane.continuousLayout=true
SplitPane.border=null
SplitPane.centerOneTouchButtons=true
SplitPane.oneTouchButtonSize={scaledNumber}6
SplitPane.oneTouchButtonOffset={scaledNumber}2
SplitPane.oneTouchButtonSize={scaledInteger}6
SplitPane.oneTouchButtonOffset={scaledInteger}2
SplitPaneDivider.border=null
SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor
@@ -374,22 +383,23 @@ TableHeader.cellBorder=2,3,2,3
#---- TextArea ----
TextArea.border=com.formdev.flatlaf.ui.FlatMarginBorder
TextArea.background=@textComponentBackground
TextArea.margin=@textComponentMargin
TextArea.background=@textComponentBackground
#---- TextField ----
TextField.border=com.formdev.flatlaf.ui.FlatBorder
TextField.background=@textComponentBackground
TextField.margin=@textComponentMargin
TextField.background=@textComponentBackground
TextField.placeholderForeground=@disabledText
#---- TextPane ----
TextPane.border=com.formdev.flatlaf.ui.FlatMarginBorder
TextPane.background=@textComponentBackground
TextPane.margin=@textComponentMargin
TextPane.background=@textComponentBackground
#---- TitledBorder ----
@@ -401,7 +411,6 @@ TitledBorder.border=1,1,1,1,@@Separator.foreground
#---- ToggleButton ----
ToggleButton.border=com.formdev.flatlaf.ui.FlatButtonBorder
ToggleButton.arc=6
ToggleButton.margin=2,14,2,14
ToggleButton.iconTextGap=4
ToggleButton.rollover=true

View File

@@ -62,21 +62,25 @@ class BasicComponentsPanel
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JComboBox<String> comboBox6 = new JComboBox<>();
JLabel textFieldLabel = new JLabel();
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField4 = new JTextField();
JTextField textField6 = new JTextField();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField2 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
JFormattedTextField formattedTextField4 = new JFormattedTextField();
JFormattedTextField formattedTextField5 = new JFormattedTextField();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField2 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
JPasswordField passwordField4 = new JPasswordField();
JPasswordField passwordField5 = new JPasswordField();
JLabel textAreaLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JTextArea textArea1 = new JTextArea();
@@ -304,6 +308,11 @@ class BasicComponentsPanel
spinner2.setEnabled(false);
add(spinner2, "cell 2 5,growx");
//---- comboBox6 ----
comboBox6.setEditable(true);
comboBox6.putClientProperty("JTextField.placeholderText", "placeholder");
add(comboBox6, "cell 5 5,growx");
//---- textFieldLabel ----
textFieldLabel.setText("JTextField:");
add(textFieldLabel, "cell 0 6");
@@ -328,6 +337,10 @@ class BasicComponentsPanel
textField4.setEditable(false);
add(textField4, "cell 4 6,growx");
//---- textField6 ----
textField6.putClientProperty("JTextField.placeholderText", "placeholder");
add(textField6, "cell 5 6,growx");
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
add(formattedTextFieldLabel, "cell 0 7");
@@ -352,6 +365,10 @@ class BasicComponentsPanel
formattedTextField4.setEditable(false);
add(formattedTextField4, "cell 4 7,growx");
//---- formattedTextField5 ----
formattedTextField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(formattedTextField5, "cell 5 7,growx");
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
add(passwordFieldLabel, "cell 0 8");
@@ -376,6 +393,10 @@ class BasicComponentsPanel
passwordField4.setEditable(false);
add(passwordField4, "cell 4 8,growx");
//---- passwordField5 ----
passwordField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(passwordField5, "cell 5 8,growx");
//---- textAreaLabel ----
textAreaLabel.setText("JTextArea:");
add(textAreaLabel, "cell 0 9");

View File

@@ -253,6 +253,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 5,growx"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox6"
"editable": true
"$client.JTextField.placeholderText": "placeholder"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 5,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textFieldLabel"
"text": "JTextField:"
@@ -287,6 +297,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 6,growx"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField6"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 6,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -321,6 +337,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 7,growx"
} )
add( new FormComponent( "javax.swing.JFormattedTextField" ) {
name: "formattedTextField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 7,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -355,6 +377,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 8,growx"
} )
add( new FormComponent( "javax.swing.JPasswordField" ) {
name: "passwordField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 8,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textAreaLabel"
"text": "JTextArea:"

View File

@@ -77,6 +77,9 @@ class ControlBar
EventQueue.invokeLater( () -> {
// update info label because user scale factor may change
updateInfoLabel();
// this is necessary because embedded JOptionPane's "steal" the default button
frame.getRootPane().setDefaultButton( closeButton );
} );
}
} );

View File

@@ -31,6 +31,14 @@ class MoreComponentsPanel
initComponents();
}
private void changeProgress() {
int value = slider3.getValue();
progressBar1.setValue( value );
progressBar2.setValue( value );
progressBar3.setValue( value );
progressBar4.setValue( value );
}
private void indeterminateCheckBoxActionPerformed() {
boolean indeterminate = indeterminateCheckBox.isSelected();
progressBar1.setIndeterminate( indeterminate );
@@ -70,7 +78,7 @@ class MoreComponentsPanel
JLabel sliderLabel = new JLabel();
JSlider slider1 = new JSlider();
JSlider slider6 = new JSlider();
JSlider slider3 = new JSlider();
slider3 = new JSlider();
JSlider slider5 = new JSlider();
JLabel progressBarLabel = new JLabel();
progressBar1 = new JProgressBar();
@@ -163,12 +171,12 @@ class MoreComponentsPanel
//---- progressBar3 ----
progressBar3.setOrientation(SwingConstants.VERTICAL);
progressBar3.setValue(50);
progressBar3.setValue(60);
add(progressBar3, "cell 4 0 1 6,growy");
//---- progressBar4 ----
progressBar4.setOrientation(SwingConstants.VERTICAL);
progressBar4.setValue(55);
progressBar4.setValue(60);
progressBar4.setStringPainted(true);
add(progressBar4, "cell 4 0 1 6,growy");
@@ -250,6 +258,7 @@ class MoreComponentsPanel
slider3.setMajorTickSpacing(50);
slider3.setPaintLabels(true);
slider3.setValue(30);
slider3.addChangeListener(e -> changeProgress());
add(slider3, "cell 1 7 3 1,aligny top,grow 100 0");
//---- slider5 ----
@@ -266,12 +275,12 @@ class MoreComponentsPanel
add(progressBarLabel, "cell 0 8");
//---- progressBar1 ----
progressBar1.setValue(50);
progressBar1.setValue(60);
add(progressBar1, "cell 1 8 3 1,growx");
//---- progressBar2 ----
progressBar2.setStringPainted(true);
progressBar2.setValue(55);
progressBar2.setValue(60);
add(progressBar2, "cell 1 8 3 1,growx");
//---- indeterminateCheckBox ----
@@ -330,6 +339,7 @@ class MoreComponentsPanel
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JProgressBar progressBar3;
private JProgressBar progressBar4;
private JSlider slider3;
private JProgressBar progressBar1;
private JProgressBar progressBar2;
private JCheckBox indeterminateCheckBox;

View File

@@ -85,7 +85,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar3"
"orientation": 1
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
@@ -95,7 +95,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar4"
"orientation": 1
"value": 55
"value": 60
"stringPainted": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
@@ -205,6 +205,10 @@ new FormModel {
"majorTickSpacing": 50
"paintLabels": true
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "changeProgress", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7 3 1,aligny top,grow 100 0"
} )
@@ -227,7 +231,7 @@ new FormModel {
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar1"
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
@@ -237,7 +241,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar2"
"stringPainted": true
"value": 55
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}

View File

@@ -5,6 +5,7 @@
package com.formdev.flatlaf.demo;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -29,6 +30,14 @@ class TabsPanel
tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy );
}
private void showTabSeparatorsChanged() {
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane2.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane3.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane4.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
}
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
@@ -96,6 +105,7 @@ class TabsPanel
JPanel panel14 = new JPanel();
moreTabsCheckBox = new JCheckBox();
tabScrollCheckBox = new JCheckBox();
showTabSeparatorsCheckBox = new JCheckBox();
hasFullBorderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
@@ -285,6 +295,7 @@ class TabsPanel
// columns
"[]" +
"[]" +
"[]" +
"[]",
// rows
"[center]"));
@@ -301,11 +312,16 @@ class TabsPanel
tabScrollCheckBox.addActionListener(e -> tabScrollChanged());
panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0");
//---- showTabSeparatorsCheckBox ----
showTabSeparatorsCheckBox.setText("JTabbedPane.showTabSeparators");
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
panel14.add(showTabSeparatorsCheckBox, "cell 2 0");
//---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder");
hasFullBorderCheckBox.setMnemonic('F');
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0");
panel14.add(hasFullBorderCheckBox, "cell 3 0,alignx left,growx 0");
}
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
}
@@ -320,6 +336,7 @@ class TabsPanel
private JTabbedPane tabbedPane4;
private JCheckBox moreTabsCheckBox;
private JCheckBox tabScrollCheckBox;
private JCheckBox showTabSeparatorsCheckBox;
private JCheckBox hasFullBorderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -199,7 +199,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][][]"
"$columnConstraints": "[][][][]"
"$rowConstraints": "[center]"
} ) {
name: "panel14"
@@ -225,6 +225,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTabSeparatorsCheckBox"
"text": "JTabbedPane.showTabSeparators"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox"
"text": "JTabbedPane.hasFullBorder"
@@ -234,7 +244,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0,alignx left,growx 0"
"value": "cell 3 0,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11
@@ -245,7 +255,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
"size": new java.awt.Dimension( 610, 515 )
} )
}
}

View File

@@ -26,7 +26,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf-jide-oss
version: 0.21
version: 0.22
Otherwise download `flatlaf-jide-oss-<version>.jar` here:

View File

@@ -17,7 +17,7 @@
package com.formdev.flatlaf.jideoss.ui;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyEquals;
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
@@ -181,7 +181,7 @@ public class FlatJideTabbedPaneUI
}
private Insets getContentBorderInsets0( int tabPlacement ) {
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( _tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight );
Insets insets = hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 );
@@ -339,7 +339,7 @@ public class FlatJideTabbedPaneUI
}
// compute insets for separator or full border
boolean hasFullBorder = this.hasFullBorder || clientPropertyEquals( _tabPane, TABBED_PANE_HAS_FULL_BORDER, true );
boolean hasFullBorder = clientPropertyBoolean( _tabPane, TABBED_PANE_HAS_FULL_BORDER, this.hasFullBorder );
int sh = scale( contentSeparatorHeight * 100 ); // multiply by 100 because rotateInsets() does not use floats
Insets ci = new Insets( 0, 0, 0, 0 );
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );

View File

@@ -33,7 +33,7 @@ build script:
groupId: com.formdev
artifactId: flatlaf-swingx
version: 0.21
version: 0.22
Otherwise download `flatlaf-swingx-<version>.jar` here:

View File

@@ -237,7 +237,7 @@ public class FlatDatePickerUI
// paint background
g2.setColor( enabled ? c.getBackground() : disabledBackground );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
// paint arrow button background
if( enabled ) {
@@ -247,7 +247,7 @@ public class FlatDatePickerUI
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.fillRoundRectangle( g2, 0, 0, width, height, focusWidth, arc );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
@@ -255,7 +255,7 @@ public class FlatDatePickerUI
g2.setColor( enabled ? borderColor : disabledBorderColor );
float lw = scale( 1f );
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 - 1 - (focusWidth * 2) ) );
paint( g, c );
}

View File

@@ -38,7 +38,15 @@ public class FlatComponentsTest
initComponents();
}
private void indeterminateCheckBoxActionPerformed() {
private void changeProgress() {
int value = slider3.getValue();
progressBar1.setValue( value );
progressBar2.setValue( value );
progressBar3.setValue( value );
progressBar4.setValue( value );
}
private void indeterminateProgress() {
boolean indeterminate = indeterminateCheckBox.isSelected();
progressBar1.setIndeterminate( indeterminate );
progressBar2.setIndeterminate( indeterminate );
@@ -85,21 +93,25 @@ public class FlatComponentsTest
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JComboBox<String> comboBox7 = new JComboBox<>();
JLabel textFieldLabel = new JLabel();
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField4 = new JTextField();
JTextField textField6 = new JTextField();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField2 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
JFormattedTextField formattedTextField4 = new JFormattedTextField();
JFormattedTextField formattedTextField5 = new JFormattedTextField();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField2 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
JPasswordField passwordField4 = new JPasswordField();
JPasswordField passwordField5 = new JPasswordField();
JLabel textAreaLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JTextArea textArea1 = new JTextArea();
@@ -166,7 +178,7 @@ public class FlatComponentsTest
JLabel sliderLabel = new JLabel();
JSlider slider1 = new JSlider();
JSlider slider6 = new JSlider();
JSlider slider3 = new JSlider();
slider3 = new JSlider();
JSlider slider5 = new JSlider();
JLabel progressBarLabel = new JLabel();
progressBar1 = new JProgressBar();
@@ -439,6 +451,11 @@ public class FlatComponentsTest
spinner2.setEnabled(false);
add(spinner2, "cell 2 6,growx");
//---- comboBox7 ----
comboBox7.setEditable(true);
comboBox7.putClientProperty("JTextField.placeholderText", "placeholder");
add(comboBox7, "cell 5 6,growx");
//---- textFieldLabel ----
textFieldLabel.setText("JTextField:");
add(textFieldLabel, "cell 0 7");
@@ -463,6 +480,10 @@ public class FlatComponentsTest
textField4.setEditable(false);
add(textField4, "cell 4 7,growx");
//---- textField6 ----
textField6.putClientProperty("JTextField.placeholderText", "placeholder");
add(textField6, "cell 5 7,growx");
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
add(formattedTextFieldLabel, "cell 0 8");
@@ -487,6 +508,10 @@ public class FlatComponentsTest
formattedTextField4.setEditable(false);
add(formattedTextField4, "cell 4 8,growx");
//---- formattedTextField5 ----
formattedTextField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(formattedTextField5, "cell 5 8,growx");
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
add(passwordFieldLabel, "cell 0 9");
@@ -511,6 +536,10 @@ public class FlatComponentsTest
passwordField4.setEditable(false);
add(passwordField4, "cell 4 9,growx");
//---- passwordField5 ----
passwordField5.putClientProperty("JTextField.placeholderText", "placeholder");
add(passwordField5, "cell 5 9,growx");
//---- textAreaLabel ----
textAreaLabel.setText("JTextArea:");
add(textAreaLabel, "cell 0 10");
@@ -737,12 +766,12 @@ public class FlatComponentsTest
//---- progressBar3 ----
progressBar3.setOrientation(SwingConstants.VERTICAL);
progressBar3.setValue(50);
progressBar3.setValue(60);
add(progressBar3, "cell 4 13 1 6,growy");
//---- progressBar4 ----
progressBar4.setOrientation(SwingConstants.VERTICAL);
progressBar4.setValue(55);
progressBar4.setValue(60);
progressBar4.setStringPainted(true);
add(progressBar4, "cell 4 13 1 6,growy");
@@ -867,6 +896,7 @@ public class FlatComponentsTest
slider3.setMajorTickSpacing(50);
slider3.setPaintLabels(true);
slider3.setValue(30);
slider3.addChangeListener(e -> changeProgress());
add(slider3, "cell 1 20 3 1,aligny top,grow 100 0");
//---- slider5 ----
@@ -883,17 +913,17 @@ public class FlatComponentsTest
add(progressBarLabel, "cell 0 21");
//---- progressBar1 ----
progressBar1.setValue(50);
progressBar1.setValue(60);
add(progressBar1, "cell 1 21 3 1,growx");
//---- progressBar2 ----
progressBar2.setStringPainted(true);
progressBar2.setValue(55);
progressBar2.setValue(60);
add(progressBar2, "cell 1 21 3 1,growx");
//---- indeterminateCheckBox ----
indeterminateCheckBox.setText("indeterminate");
indeterminateCheckBox.addActionListener(e -> indeterminateCheckBoxActionPerformed());
indeterminateCheckBox.addActionListener(e -> indeterminateProgress());
add(indeterminateCheckBox, "cell 4 21");
//---- toolTipLabel ----
@@ -952,6 +982,7 @@ public class FlatComponentsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JProgressBar progressBar3;
private JProgressBar progressBar4;
private JSlider slider3;
private JProgressBar progressBar1;
private JProgressBar progressBar2;
private JCheckBox indeterminateCheckBox;

View File

@@ -313,6 +313,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 6,growx"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox7"
"editable": true
"$client.JTextField.placeholderText": "placeholder"
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 6,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textFieldLabel"
"text": "JTextField:"
@@ -347,6 +357,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 7,growx"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField6"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 7,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -381,6 +397,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 8,growx"
} )
add( new FormComponent( "javax.swing.JFormattedTextField" ) {
name: "formattedTextField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 8,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -415,6 +437,12 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 9,growx"
} )
add( new FormComponent( "javax.swing.JPasswordField" ) {
name: "passwordField5"
"$client.JTextField.placeholderText": "placeholder"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 5 9,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "textAreaLabel"
"text": "JTextArea:"
@@ -673,7 +701,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar3"
"orientation": 1
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
@@ -683,7 +711,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar4"
"orientation": 1
"value": 55
"value": 60
"stringPainted": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
@@ -836,6 +864,10 @@ new FormModel {
"majorTickSpacing": 50
"paintLabels": true
"value": 30
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "changeProgress", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 20 3 1,aligny top,grow 100 0"
} )
@@ -858,7 +890,7 @@ new FormModel {
} )
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar1"
"value": 50
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
@@ -868,7 +900,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JProgressBar" ) {
name: "progressBar2"
"stringPainted": true
"value": 55
"value": 60
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
@@ -881,7 +913,7 @@ new FormModel {
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateCheckBoxActionPerformed", false ) )
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "indeterminateProgress", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 4 21"
} )
@@ -945,7 +977,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 750 )
"size": new java.awt.Dimension( 865, 750 )
} )
}
}

View File

@@ -5,6 +5,7 @@
package com.formdev.flatlaf.testing;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
@@ -36,6 +37,14 @@ public class FlatContainerTest
tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy );
}
private void showTabSeparatorsChanged() {
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane2.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane3.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
tabbedPane4.putClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
}
private void hasFullBorderChanged() {
Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null;
tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder );
@@ -100,6 +109,7 @@ public class FlatContainerTest
JPanel panel14 = new JPanel();
moreTabsCheckBox = new JCheckBox();
tabScrollCheckBox = new JCheckBox();
showTabSeparatorsCheckBox = new JCheckBox();
hasFullBorderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
@@ -291,6 +301,7 @@ public class FlatContainerTest
// columns
"[]" +
"[]" +
"[]" +
"[]",
// rows
"[center]"));
@@ -307,11 +318,16 @@ public class FlatContainerTest
tabScrollCheckBox.addActionListener(e -> tabScrollChanged());
panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0");
//---- showTabSeparatorsCheckBox ----
showTabSeparatorsCheckBox.setText("JTabbedPane.showTabSeparators");
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
panel14.add(showTabSeparatorsCheckBox, "cell 2 0");
//---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder");
hasFullBorderCheckBox.setMnemonic('F');
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0");
panel14.add(hasFullBorderCheckBox, "cell 3 0,alignx left,growx 0");
}
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
}
@@ -326,6 +342,7 @@ public class FlatContainerTest
private JTabbedPane tabbedPane4;
private JCheckBox moreTabsCheckBox;
private JCheckBox tabScrollCheckBox;
private JCheckBox showTabSeparatorsCheckBox;
private JCheckBox hasFullBorderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -200,7 +200,7 @@ new FormModel {
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][][]"
"$columnConstraints": "[][][][]"
"$rowConstraints": "[center]"
} ) {
name: "panel14"
@@ -227,6 +227,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTabSeparatorsCheckBox"
"text": "JTabbedPane.showTabSeparators"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox"
"text": "JTabbedPane.hasFullBorder"
@@ -236,7 +246,7 @@ new FormModel {
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0,alignx left,growx 0"
"value": "cell 3 0,alignx left,growx 0"
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11
@@ -247,7 +257,7 @@ new FormModel {
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
"size": new java.awt.Dimension( 625, 515 )
} )
}
}

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.testing;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
@@ -25,9 +26,16 @@ import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.lang.reflect.Field;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
@@ -35,6 +43,8 @@ import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.JToolBar;
import javax.swing.JToolTip;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
@@ -53,7 +63,10 @@ public class FlatInspector
private static final Integer HIGHLIGHT_LAYER = 401;
private static final Integer TOOLTIP_LAYER = 402;
private static final int KEY_MODIFIERS_MASK = InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK;
private final JRootPane rootPane;
private final MouseMotionListener mouseMotionListener;
private Component lastComponent;
private int lastX;
@@ -63,10 +76,38 @@ public class FlatInspector
private JComponent highlightFigure;
private JToolTip tip;
/**
* Installs a key listener into the application that allows enabling and disabling
* the UI inspector with the given keystroke (e.g. "ctrl shift alt X").
*/
public static void install( String activationKeys ) {
KeyStroke keyStroke = KeyStroke.getKeyStroke( activationKeys );
Toolkit.getDefaultToolkit().addAWTEventListener( e -> {
if( e.getID() == KeyEvent.KEY_RELEASED &&
((KeyEvent)e).getKeyCode() == keyStroke.getKeyCode() &&
(((KeyEvent)e).getModifiersEx() & KEY_MODIFIERS_MASK) == (keyStroke.getModifiers() & KEY_MODIFIERS_MASK) )
{
Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
if( activeWindow instanceof RootPaneContainer ) {
JRootPane rootPane = ((RootPaneContainer)activeWindow).getRootPane();
FlatInspector inspector = (FlatInspector) rootPane.getClientProperty( FlatInspector.class );
if( inspector == null ) {
inspector = new FlatInspector( rootPane );
rootPane.putClientProperty( FlatInspector.class, inspector );
inspector.setEnabled( true );
} else {
inspector.uninstall();
rootPane.putClientProperty( FlatInspector.class, null );
}
}
}
}, AWTEvent.KEY_EVENT_MASK );
}
public FlatInspector( JRootPane rootPane ) {
this.rootPane = rootPane;
rootPane.getGlassPane().addMouseMotionListener( new MouseMotionAdapter() {
mouseMotionListener = new MouseMotionAdapter() {
@Override
public void mouseMoved( MouseEvent e ) {
lastX = e.getX();
@@ -74,7 +115,15 @@ public class FlatInspector
inspectParent = e.isShiftDown();
inspect( lastX, lastY );
}
} );
};
rootPane.getGlassPane().addMouseMotionListener( mouseMotionListener );
}
private void uninstall() {
setEnabled( false );
rootPane.getGlassPane().setVisible( false );
rootPane.getGlassPane().removeMouseMotionListener( mouseMotionListener );
}
public void setEnabled( boolean enabled ) {
@@ -106,7 +155,8 @@ public class FlatInspector
private void inspect( int x, int y ) {
Container contentPane = rootPane.getContentPane();
Component c = SwingUtilities.getDeepestComponentAt( contentPane, x, y );
Point pt = SwingUtilities.convertPoint( rootPane.getGlassPane(), x, y, contentPane );
Component c = SwingUtilities.getDeepestComponentAt( contentPane, pt.x, pt.y );
if( inspectParent && c != null && c != contentPane )
c = c.getParent();
if( c == contentPane || (c != null && c.getParent() == contentPane) )
@@ -182,9 +232,9 @@ public class FlatInspector
// position the tip in the visible area
Rectangle visibleRect = rootPane.getVisibleRect();
if( tx + size.width > visibleRect.x + visibleRect.width )
tx = visibleRect.x + visibleRect.width - size.width;
tx -= size.width + UIScale.scale( 16 );
if( ty + size.height > visibleRect.y + visibleRect.height )
ty = visibleRect.y + visibleRect.height - size.height;
ty -= size.height + UIScale.scale( 32 );
if( tx < visibleRect.x )
tx = visibleRect.x;
if( ty < visibleRect.y )

View File

@@ -0,0 +1,164 @@
/*
* Created by JFormDesigner on Tue Aug 27 21:47:02 CEST 2019
*/
package com.formdev.flatlaf.testing;
import java.awt.*;
import java.beans.PropertyVetoException;
import javax.swing.*;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatInternalFrameTest
extends FlatTestPanel
{
private static final int GAP = 20;
private final int frameX;
private final int frameY;
private int frameCount = 0;
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatInternalFrameTest" );
frame.showFrame( FlatInternalFrameTest::new );
} );
}
public FlatInternalFrameTest() {
initComponents();
frameX = palette.getX() + palette.getWidth() + UIScale.scale( GAP );
frameY = UIScale.scale( GAP );
createInternalFrame();
}
private void createInternalFrame() {
String title = titleField.getText();
if( title.isEmpty() )
title = "Frame " + (frameCount + 1);
JInternalFrame internalFrame = new JInternalFrame( title,
resizableCheckBox.isSelected(),
closableCheckBox.isSelected(),
maximizableCheckBox.isSelected(),
iconifiableCheckBox.isSelected() );
JPanel panel = new JPanel();
panel.setBackground( new Color( (int) (Math.random() * 0xffffff) ) );
internalFrame.setContentPane( panel );
internalFrame.setBounds( frameX + UIScale.scale( GAP ) * (frameCount % 10),
frameY + UIScale.scale( GAP ) * (frameCount % 10), UIScale.scale( 200 ), UIScale.scale( 200 ) );
desktopPane.add( internalFrame, JLayeredPane.DEFAULT_LAYER );
try {
internalFrame.setSelected( true );
} catch( PropertyVetoException ex ) {
// ignore
}
internalFrame.show();
frameCount++;
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
desktopPane = new JDesktopPane();
palette = new JInternalFrame();
resizableCheckBox = new JCheckBox();
closableCheckBox = new JCheckBox();
iconifiableCheckBox = new JCheckBox();
maximizableCheckBox = new JCheckBox();
titleLabel = new JLabel();
titleField = new JTextField();
createFrameButton = new JButton();
//======== this ========
setLayout(new MigLayout(
"insets dialog,hidemode 3",
// columns
"[grow,fill]",
// rows
"[grow,fill]"));
//======== desktopPane ========
{
//======== palette ========
{
palette.setVisible(true);
palette.setTitle("Internal Frame Generator");
palette.setResizable(true);
palette.putClientProperty("JInternalFrame.isPalette", true);
palette.setIconifiable(true);
Container paletteContentPane = palette.getContentPane();
paletteContentPane.setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]" +
"[fill]",
// rows
"[fill]0" +
"[]0" +
"[]unrel" +
"[]unrel"));
//---- resizableCheckBox ----
resizableCheckBox.setText("Resizable");
resizableCheckBox.setSelected(true);
paletteContentPane.add(resizableCheckBox, "cell 0 0,alignx left,growx 0");
//---- closableCheckBox ----
closableCheckBox.setText("Closable");
closableCheckBox.setSelected(true);
paletteContentPane.add(closableCheckBox, "cell 1 0,alignx left,growx 0");
//---- iconifiableCheckBox ----
iconifiableCheckBox.setText("Iconifiable");
iconifiableCheckBox.setSelected(true);
paletteContentPane.add(iconifiableCheckBox, "cell 0 1,alignx left,growx 0");
//---- maximizableCheckBox ----
maximizableCheckBox.setText("Maximizable");
maximizableCheckBox.setSelected(true);
paletteContentPane.add(maximizableCheckBox, "cell 1 1,alignx left,growx 0");
//---- titleLabel ----
titleLabel.setText("Frame title:");
paletteContentPane.add(titleLabel, "cell 0 2");
paletteContentPane.add(titleField, "cell 1 2");
//---- createFrameButton ----
createFrameButton.setText("Create Frame");
createFrameButton.addActionListener(e -> createInternalFrame());
paletteContentPane.add(createFrameButton, "cell 1 3,alignx right,growx 0");
}
desktopPane.add(palette, JLayeredPane.PALETTE_LAYER);
palette.setBounds(15, 25, 220, 160);
}
add(desktopPane, "cell 0 0,width 600,height 600");
// JFormDesigner - End of component initialization //GEN-END:initComponents
if( UIScale.getUserScaleFactor() > 1 )
palette.setSize( UIScale.scale( palette.getSize() ) );
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JDesktopPane desktopPane;
private JInternalFrame palette;
private JCheckBox resizableCheckBox;
private JCheckBox closableCheckBox;
private JCheckBox iconifiableCheckBox;
private JCheckBox maximizableCheckBox;
private JLabel titleLabel;
private JTextField titleField;
private JButton createFrameButton;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,86 @@
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": "insets dialog,hidemode 3"
"$columnConstraints": "[grow,fill]"
"$rowConstraints": "[grow,fill]"
} ) {
name: "this"
add( new FormContainer( "javax.swing.JDesktopPane", new FormLayoutManager( class javax.swing.JDesktopPane ) ) {
name: "desktopPane"
add( new FormContainer( "javax.swing.JInternalFrame", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill][fill]"
"$rowConstraints": "[fill]0[]0[]unrel[]unrel"
} ) {
name: "palette"
"visible": true
"title": "Internal Frame Generator"
"resizable": true
"$client.JInternalFrame.isPalette": true
"iconifiable": true
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "resizableCheckBox"
"text": "Resizable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "closableCheckBox"
"text": "Closable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "iconifiableCheckBox"
"text": "Iconifiable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maximizableCheckBox"
"text": "Maximizable"
"selected": true
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "titleLabel"
"text": "Frame title:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "titleField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "createFrameButton"
"text": "Create Frame"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "createInternalFrame", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3,alignx right,growx 0"
} )
}, new FormLayoutConstraints( null ) {
"x": 15
"y": 25
"width": 220
"height": 160
"layer": 100
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,width 600,height 600"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 500, 515 )
} )
}
}

View File

@@ -143,6 +143,9 @@ public class FlatTestFrame
KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
// make the "close" button the default button
getRootPane().setDefaultButton( closeButton );
// close frame
closeButton.addActionListener(e -> dispose());
@@ -170,6 +173,9 @@ public class FlatTestFrame
// enable/disable scale factor combobox
updateScaleFactorComboBox();
// this is necessary because embedded JOptionPane's "steal" the default button
getRootPane().setDefaultButton( closeButton );
} );
}
} );

View File

@@ -229,10 +229,13 @@ SplitPaneDivider.oneTouchHoverArrowColor=#ff0000
#---- TabbedPane ----
TabbedPane.disabledForeground=#777777
TabbedPane.selectedBackground=#0f0
TabbedPane.selectedForeground=#00f
TabbedPane.underlineColor=#4A88C7
TabbedPane.disabledUnderlineColor=#7a7a7a
TabbedPane.hoverColor=#eeeeee
TabbedPane.focusColor=#dddddd
TabbedPane.tabSeparatorColor=#00f
TabbedPane.contentAreaColor=#bbbbbb