Compare commits

..

15 Commits
1.4 ... 1.5

Author SHA1 Message Date
Karl Tauber
6fcee03752 release 1.5 2021-08-04 15:13:58 +02:00
Karl Tauber
5782ceeb5d README.md: added descriptions to addons 2021-08-04 14:27:57 +02:00
Karl Tauber
f752db5892 FileChooser: fixed missing (localized) texts when FlatLaf is loaded in special classloader
(e.g. plugin system in Apache NetBeans)

https://issues.apache.org/jira/browse/NETBEANS-5865
2021-08-04 11:15:18 +02:00
Karl Tauber
bce58bc97b SwingX: added search and clear icons to JXSearchField (issue #359) 2021-08-03 17:52:49 +02:00
Karl Tauber
d373687bc4 Testing: added FlatSingleComponentTest to easier test/debug single components 2021-08-03 15:16:04 +02:00
Karl Tauber
e5e510c825 Demo: fixed inconsistent behavior when first changing font size and then font family, which did loose user scale factor on Windows in Java 9+ (issue #352) 2021-08-02 19:16:38 +02:00
Karl Tauber
29064ec72f Button and TextComponent: do not apply minimum width/height if margins are set (issue #364) 2021-08-02 18:36:10 +02:00
Karl Tauber
953eee1dc8 TableHeader: made getRolloverColumn() public to allow usage in custom renderers (issue #336) 2021-08-02 18:01:08 +02:00
Karl Tauber
75f76f4875 ComboBox and Spinner: limit arrow button width if component has large preferred height (issue #361) 2021-08-02 15:27:25 +02:00
Karl Tauber
ecfbe68c33 Native window decorations: updated DLLs (issues #357 and #339)
built by GitHub Actions:
https://github.com/JFormDesigner/FlatLaf/actions/runs/1085691279
2021-07-31 21:22:09 +02:00
Karl Tauber
7f02eb9cf0 Native window decorations: when window is initially shown, fill background with window background color (instead of white), which avoids flickering in dark themes (issue #339) 2021-07-31 21:05:01 +02:00
Karl Tauber
4ab90065dc Native window decorations: when resizing a window to the right or to the bottom, then first fill the new space with the window background color (instead of black) before the layout is updated (issue #339) 2021-07-31 18:02:10 +02:00
Karl Tauber
d3e39a1359 Native window decorations: fixed occasional application crash on Windows 10 in flatlaf-windows.dll (issue #357) 2021-07-30 23:06:09 +02:00
Karl Tauber
60e5861de4 InternalFrame: limit internal frame bounds to parent bounds on resize; honor maximum size of internal frame (issue #362) 2021-07-29 16:44:50 +02:00
Karl Tauber
ca7f5045ae Popup: fixed incorrectly placed drop shadow for medium-weight popups in maximized windows (issue #358) 2021-07-29 15:39:16 +02:00
47 changed files with 1801 additions and 78 deletions

View File

@@ -1,6 +1,37 @@
FlatLaf Change Log
==================
## 1.5
#### New features and improvements
- SwingX: Added search and clear icons to `JXSearchField`. (issue #359)
#### Fixed bugs
- Button and TextComponent: Do not apply minimum width/height if margins are
set. (issue #364)
- ComboBox and Spinner: Limit arrow button width if component has large
preferred height. (issue #361)
- FileChooser: Fixed missing (localized) texts when FlatLaf is loaded in special
classloader (e.g. plugin system in Apache NetBeans).
- InternalFrame: Limit internal frame bounds to parent bounds on resize. Also
honor maximum size of internal frame. (issue #362)
- Popup: Fixed incorrectly placed drop shadow for medium-weight popups in
maximized windows. (issue #358)
- Native window decorations (Windows 10 only):
- Fixed occasional application crash in `flatlaf-windows.dll`. (issue #357)
- When window is initially shown, fill background with window background color
(instead of white), which avoids flickering in dark themes. (issue 339)
- When resizing a window at the right/bottom edge, then first fill the new
space with the window background color (instead of black) before the layout
is updated.
- When resizing a window at the left/top edge, then first fill the new space
with the window background color (instead of garbage) before the layout is
updated.
## 1.4
#### New features and improvements
@@ -13,7 +44,7 @@ FlatLaf Change Log
- Table and PopupFactory: Use `StackWalker` in Java 9+ for better performance.
(issue #334)
- ToolBar: Paint focus indicator for focused button in toolbar. (issue #346)
- ToolBar: Support focusable buttons in toolbar (set UI values
- ToolBar: Support focusable buttons in toolbar (set UI value
`ToolBar.focusableButtons` to `true`). (issue #346)
#### Fixed bugs

View File

@@ -67,10 +67,13 @@ docs).
Addons
------
- [IntelliJ Themes Pack](flatlaf-intellij-themes)
- [Extras](flatlaf-extras)
- [SwingX](flatlaf-swingx)
- [JIDE Common Layer](flatlaf-jide-oss)
- [IntelliJ Themes Pack](flatlaf-intellij-themes) - bundles many popular
open-source 3rd party themes
- [Extras](flatlaf-extras) - SVG icon, tri-state check box, UI inspectors, and
more
- [SwingX](flatlaf-swingx) - support for SwingX components
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
components
Getting started

View File

@@ -14,8 +14,8 @@
* limitations under the License.
*/
val releaseVersion = "1.4"
val developmentVersion = "1.5-SNAPSHOT"
val releaseVersion = "1.5"
val developmentVersion = "1.6-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion

View File

@@ -32,10 +32,13 @@ import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.ServiceLoader;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -66,6 +69,7 @@ import com.formdev.flatlaf.ui.FlatRootPaneUI;
import com.formdev.flatlaf.util.GrayFilter;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
@@ -356,8 +360,8 @@ public abstract class FlatLaf
// (can be queried without using FlatLaf API)
defaults.put( "laf.dark", isDark() );
// add resource bundle for localized texts
defaults.addResourceBundle( "com.formdev.flatlaf.resources.Bundle" );
// init resource bundle for localized texts
initResourceBundle( defaults, "com.formdev.flatlaf.resources.Bundle" );
// initialize some defaults (for overriding) that are used in UI delegates,
// but are not set in BasicLookAndFeel
@@ -453,6 +457,45 @@ public abstract class FlatLaf
return null;
}
private void initResourceBundle( UIDefaults defaults, String bundleName ) {
// add resource bundle for localized texts
defaults.addResourceBundle( bundleName );
// Check whether Swing can not load the FlatLaf resource bundle,
// which can happen in applications that use some plugin system
// and load FlatLaf in a plugin that uses its own classloader.
// (e.g. Apache NetBeans)
if( defaults.get( "FileChooser.fileNameHeaderText" ) != null )
return;
// load FlatLaf resource bundle and add content to defaults
try {
ResourceBundle bundle = ResourceBundle.getBundle( bundleName, defaults.getDefaultLocale() );
Enumeration<String> keys = bundle.getKeys();
while( keys.hasMoreElements() ) {
String key = keys.nextElement();
String value = bundle.getString( key );
String baseKey = StringUtils.removeTrailing( key, ".textAndMnemonic" );
if( baseKey != key ) {
String text = value.replace( "&", "" );
String mnemonic = null;
int index = value.indexOf( '&' );
if( index >= 0 )
mnemonic = Integer.toString( Character.toUpperCase( value.charAt( index + 1 ) ) );
defaults.put( baseKey + "Text", text );
if( mnemonic != null )
defaults.put( baseKey + "Mnemonic", mnemonic );
} else
defaults.put( key, value );
}
} catch( MissingResourceException ex ) {
LoggingFacade.INSTANCE.logSevere( null, ex );
}
}
private void initFonts( UIDefaults defaults ) {
FontUIResource uiFont = null;

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2021 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
*
* https://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.icons;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* "clear" icon for search fields.
*
* @uiDefault SearchField.clearIconColor Color
* @uiDefault SearchField.clearIconHoverColor Color
* @uiDefault SearchField.clearIconPressedColor Color
*
* @author Karl Tauber
* @since 1.5
*/
public class FlatClearIcon
extends FlatAbstractIcon
{
protected Color clearIconColor = UIManager.getColor( "SearchField.clearIconColor" );
protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
public FlatClearIcon() {
super( 16, 16, null );
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
if( c instanceof AbstractButton ) {
ButtonModel model = ((AbstractButton)c).getModel();
if( model.isPressed() || model.isRollover() ) {
/*
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#7F8B91" fill-opacity=".5" fill-rule="evenodd" d="M8,1.75 C11.4517797,1.75 14.25,4.54822031 14.25,8 C14.25,11.4517797 11.4517797,14.25 8,14.25 C4.54822031,14.25 1.75,11.4517797 1.75,8 C1.75,4.54822031 4.54822031,1.75 8,1.75 Z M10.5,4.5 L8,7 L5.5,4.5 L4.5,5.5 L7,8 L4.5,10.5 L5.5,11.5 L8,9 L10.5,11.5 L11.5,10.5 L9,8 L11.5,5.5 L10.5,4.5 Z"/>
</svg>
*/
// paint filled circle with cross
g.setColor( model.isPressed() ? clearIconPressedColor : clearIconHoverColor );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Ellipse2D.Float( 1.75f, 1.75f, 12.5f, 12.5f ), false );
path.append( FlatUIUtils.createPath( 4.5,5.5, 5.5,4.5, 8,7, 10.5,4.5, 11.5,5.5, 9,8, 11.5,10.5, 10.5,11.5, 8,9, 5.5,11.5, 4.5,10.5, 7,8 ), false );
g.fill( path );
return;
}
}
/*
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="none" stroke="#7F8B91" stroke-linecap="square" stroke-opacity=".5" d="M5,5 L11,11 M5,11 L11,5"/>
</svg>
*/
// paint cross
g.setColor( clearIconColor );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Line2D.Float( 5,5, 11,11 ), false );
path.append( new Line2D.Float( 5,11, 11,5 ), false );
g.draw( path );
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2021 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
*
* https://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.icons;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatButtonUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* "search" icon for search fields.
*
* @uiDefault SearchField.searchIconColor Color
* @uiDefault SearchField.searchIconHoverColor Color
* @uiDefault SearchField.searchIconPressedColor Color
*
* @author Karl Tauber
* @since 1.5
*/
public class FlatSearchIcon
extends FlatAbstractIcon
{
protected Color searchIconColor = UIManager.getColor( "SearchField.searchIconColor" );
protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
public FlatSearchIcon() {
super( 16, 16, null );
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
/*
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
<polygon fill="#7F8B91" points="10.813 9.75 14 12.938 12.938 14 9.75 10.813"/>
<path fill="#7F8B91" d="M7,2 C9.76142375,2 12,4.23857625 12,7 C12,9.76142375 9.76142375,12 7,12 C4.23857625,12 2,9.76142375 2,7 C2,4.23857625 4.23857625,2 7,2 Z M7,3 C4.790861,3 3,4.790861 3,7 C3,9.209139 4.790861,11 7,11 C9.209139,11 11,9.209139 11,7 C11,4.790861 9.209139,3 7,3 Z"/>
</g>
</svg>
*/
g.setColor( FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
null, searchIconHoverColor, searchIconPressedColor ) );
// paint magnifier
Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
g.fill( area );
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2021 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
*
* https://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.icons;
import java.awt.Component;
import java.awt.Graphics2D;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
* "search with history" icon for search fields.
*
* @author Karl Tauber
* @since 1.5
*/
public class FlatSearchWithHistoryIcon
extends FlatSearchIcon
{
public FlatSearchWithHistoryIcon() {
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
/*
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
<polygon fill="#7F8B91" points="8.813 9.75 12 12.938 10.938 14 7.75 10.813"/>
<path fill="#7F8B91" d="M5,2 C7.76142375,2 10,4.23857625 10,7 C10,9.76142375 7.76142375,12 5,12 C2.23857625,12 0,9.76142375 0,7 C0,4.23857625 2.23857625,2 5,2 Z M5,3 C2.790861,3 1,4.790861 1,7 C1,9.209139 2.790861,11 5,11 C7.209139,11 9,9.209139 9,7 C9,4.790861 7.209139,3 5,3 Z"/>
<polygon fill="#7F8B91" points="11 7 16 7 13.5 10"/>
</g>
</svg>
*/
// paint magnifier
g.translate( -2, 0 );
super.paintIcon( c, g );
g.translate( 2, 0 );
// paint history arrow
g.fill( FlatUIUtils.createPath( 11,7, 16,7, 13.5,10 ) );
}
}

View File

@@ -30,6 +30,7 @@ import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.util.Objects;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
@@ -129,6 +130,7 @@ public class FlatButtonUI
protected Color toolbarSelectedBackground;
private Icon helpButtonIcon;
private Insets defaultMargin;
private boolean defaults_initialized = false;
@@ -184,6 +186,7 @@ public class FlatButtonUI
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
defaultMargin = UIManager.getInsets( prefix + "margin" );
defaults_initialized = true;
}
@@ -499,7 +502,9 @@ public class FlatButtonUI
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
// make single-character-no-icon button square (increase width)
prefSize.width = Math.max( prefSize.width, prefSize.height );
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) &&
c.getBorder() instanceof FlatButtonBorder && hasDefaultMargins( c ) )
{
// apply minimum width/height
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
@@ -509,6 +514,11 @@ public class FlatButtonUI
return prefSize;
}
private boolean hasDefaultMargins( JComponent c ) {
Insets margin = ((AbstractButton)c).getMargin();
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
}
//---- class FlatButtonListener -------------------------------------------
protected class FlatButtonListener

View File

@@ -23,6 +23,7 @@ import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
@@ -261,8 +262,12 @@ public class FlatComboBoxUI
super.layoutContainer( parent );
if( arrowButton != null ) {
// limit button width to height of a raw combobox (without insets)
FontMetrics fm = comboBox.getFontMetrics( comboBox.getFont() );
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
Insets insets = getInsets();
int buttonWidth = parent.getPreferredSize().height - insets.top - insets.bottom;
int buttonWidth = Math.min( parent.getPreferredSize().height - insets.top - insets.bottom, maxButtonWidth );
if( buttonWidth != arrowButton.getWidth() ) {
// set width of arrow button to preferred height of combobox
int xOffset = comboBox.getComponentOrientation().isLeftToRight()

View File

@@ -21,6 +21,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
@@ -65,6 +66,8 @@ public class FlatEditorPaneUI
protected boolean isIntelliJTheme;
protected Color focusedBackground;
private Insets defaultMargin;
private Object oldHonorDisplayProperties;
private FocusListener focusListener;
@@ -81,6 +84,8 @@ public class FlatEditorPaneUI
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
defaultMargin = UIManager.getInsets( prefix + ".margin" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
@@ -128,15 +133,19 @@ public class FlatEditorPaneUI
@Override
public Dimension getPreferredSize( JComponent c ) {
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
}
@Override
public Dimension getMinimumSize( JComponent c ) {
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth, defaultMargin );
}
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth, Insets defaultMargin ) {
// do not apply minimum width if JTextComponent.margin is set
if( !FlatTextFieldUI.hasDefaultMargins( c, defaultMargin ) )
return size;
// Assume that text area is in a scroll pane (that displays the border)
// and subtract 1px border line width.
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding

View File

@@ -489,6 +489,9 @@ public class FlatPopupFactory
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
layeredPane.add( dropShadowPanel, JLayeredPane.POPUP_LAYER, 0 );
moveMediumWeightDropShadow();
resizeMediumWeightDropShadow();
mediumPanelListener = new ComponentListener() {
@Override
public void componentShown( ComponentEvent e ) {
@@ -504,17 +507,12 @@ public class FlatPopupFactory
@Override
public void componentMoved( ComponentEvent e ) {
if( dropShadowPanel != null && mediumWeightPanel != null ) {
Point location = mediumWeightPanel.getLocation();
Insets insets = dropShadowPanel.getInsets();
dropShadowPanel.setLocation( location.x - insets.left, location.y - insets.top );
}
moveMediumWeightDropShadow();
}
@Override
public void componentResized( ComponentEvent e ) {
if( dropShadowPanel != null )
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
resizeMediumWeightDropShadow();
}
};
mediumWeightPanel.addComponentListener( mediumPanelListener );
@@ -530,5 +528,18 @@ public class FlatPopupFactory
parent.repaint( bounds.x, bounds.y, bounds.width, bounds.height );
}
}
private void moveMediumWeightDropShadow() {
if( dropShadowPanel != null && mediumWeightPanel != null ) {
Point location = mediumWeightPanel.getLocation();
Insets insets = dropShadowPanel.getInsets();
dropShadowPanel.setLocation( location.x - insets.left, location.y - insets.top );
}
}
private void resizeMediumWeightDropShadow() {
if( dropShadowPanel != null && mediumWeightPanel != null )
dropShadowPanel.setSize( FlatUIUtils.addInsets( mediumWeightPanel.getSize(), dropShadowPanel.getInsets() ) );
}
}
}

View File

@@ -21,6 +21,7 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
@@ -411,8 +412,12 @@ public class FlatSpinnerUI
Rectangle editorRect = new Rectangle( r );
Rectangle buttonsRect = new Rectangle( r );
// limit buttons width to height of a raw spinner (without insets)
FontMetrics fm = spinner.getFontMetrics( spinner.getFont() );
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
// make button area square (if spinner has preferred height)
int buttonsWidth = parent.getPreferredSize().height - insets.top - insets.bottom;
int buttonsWidth = Math.min( parent.getPreferredSize().height - insets.top - insets.bottom, maxButtonWidth );
buttonsRect.width = buttonsWidth;
if( parent.getComponentOrientation().isLeftToRight() ) {

View File

@@ -94,6 +94,12 @@ public class FlatTableHeaderUI
bottomSeparatorColor = null;
}
// overridden and made public to allow usage in custom renderers
@Override
public int getRolloverColumn() {
return super.getRolloverColumn();
}
@Override
public void paint( Graphics g, JComponent c ) {
TableColumnModel columnModel = header.getColumnModel();

View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
@@ -67,6 +68,8 @@ public class FlatTextAreaUI
protected Color inactiveBackground;
protected Color focusedBackground;
private Insets defaultMargin;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
@@ -90,6 +93,8 @@ public class FlatTextAreaUI
disabledBackground = UIManager.getColor( "TextArea.disabledBackground" );
inactiveBackground = UIManager.getColor( "TextArea.inactiveBackground" );
focusedBackground = UIManager.getColor( "TextArea.focusedBackground" );
defaultMargin = UIManager.getInsets( "TextArea.margin" );
}
@Override
@@ -170,7 +175,7 @@ public class FlatTextAreaUI
if( c instanceof JTextArea && ((JTextArea)c).getColumns() > 0 )
return size;
return FlatEditorPaneUI.applyMinimumWidth( c, size, minimumWidth );
return FlatEditorPaneUI.applyMinimumWidth( c, size, minimumWidth, defaultMargin );
}
@Override

View File

@@ -27,6 +27,7 @@ import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.util.Objects;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JSpinner;
@@ -80,6 +81,8 @@ public class FlatTextFieldUI
protected Color placeholderForeground;
protected Color focusedBackground;
private Insets defaultMargin;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
@@ -96,6 +99,8 @@ public class FlatTextFieldUI
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
defaultMargin = UIManager.getInsets( prefix + ".margin" );
LookAndFeel.installProperty( getComponent(), "opaque", false );
MigLayoutVisualPadding.install( getComponent() );
@@ -250,11 +255,15 @@ public class FlatTextFieldUI
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
}
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
private Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
// do not apply minimum width if JTextField.columns is set
if( c instanceof JTextField && ((JTextField)c).getColumns() > 0 )
return size;
// do not apply minimum width if JTextComponent.margin is set
if( !hasDefaultMargins( c, defaultMargin ) )
return size;
// do not apply minimum width if used in combobox or spinner
Container parent = c.getParent();
if( parent instanceof JComboBox ||
@@ -268,6 +277,11 @@ public class FlatTextFieldUI
return size;
}
static boolean hasDefaultMargins( JComponent c, Insets defaultMargin ) {
Insets margin = ((JTextComponent)c).getMargin();
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
}
@Override
protected Rectangle getVisibleEditorRect() {
Rectangle r = super.getVisibleEditorRect();

View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
@@ -62,6 +63,8 @@ public class FlatTextPaneUI
protected boolean isIntelliJTheme;
protected Color focusedBackground;
private Insets defaultMargin;
private Object oldHonorDisplayProperties;
private FocusListener focusListener;
@@ -78,6 +81,8 @@ public class FlatTextPaneUI
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
defaultMargin = UIManager.getInsets( prefix + ".margin" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, true );
@@ -117,12 +122,12 @@ public class FlatTextPaneUI
@Override
public Dimension getPreferredSize( JComponent c ) {
return FlatEditorPaneUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
return FlatEditorPaneUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
}
@Override
public Dimension getMinimumSize( JComponent c ) {
return FlatEditorPaneUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
return FlatEditorPaneUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth, defaultMargin );
}
@Override

View File

@@ -181,8 +181,12 @@ public abstract class FlatWindowResizer
protected abstract boolean isWindowResizable();
protected abstract Rectangle getWindowBounds();
protected abstract void setWindowBounds( Rectangle r );
protected abstract boolean limitToParentBounds();
protected abstract Rectangle getParentBounds();
protected abstract boolean honorMinimumSizeOnResize();
protected abstract boolean honorMaximumSizeOnResize();
protected abstract Dimension getWindowMinimumSize();
protected abstract Dimension getWindowMaximumSize();
protected void beginResizing( int direction ) {}
protected void endResizing() {}
@@ -283,6 +287,16 @@ public abstract class FlatWindowResizer
}
}
@Override
protected boolean limitToParentBounds() {
return false;
}
@Override
protected Rectangle getParentBounds() {
return null;
}
@Override
protected boolean honorMinimumSizeOnResize() {
return
@@ -290,11 +304,21 @@ public abstract class FlatWindowResizer
(honorDialogMinimumSizeOnResize && window instanceof Dialog);
}
@Override
protected boolean honorMaximumSizeOnResize() {
return false;
}
@Override
protected Dimension getWindowMinimumSize() {
return window.getMinimumSize();
}
@Override
protected Dimension getWindowMaximumSize() {
return window.getMaximumSize();
}
@Override
boolean isDialog() {
return window instanceof Dialog;
@@ -354,16 +378,36 @@ public abstract class FlatWindowResizer
desktopManager.get().resizeFrame( getFrame(), r.x, r.y, r.width, r.height );
}
@Override
protected boolean limitToParentBounds() {
return true;
}
@Override
protected Rectangle getParentBounds() {
return getFrame().getParent().getBounds();
}
@Override
protected boolean honorMinimumSizeOnResize() {
return true;
}
@Override
protected boolean honorMaximumSizeOnResize() {
return true;
}
@Override
protected Dimension getWindowMinimumSize() {
return getFrame().getMinimumSize();
}
@Override
protected Dimension getWindowMaximumSize() {
return getFrame().getMaximumSize();
}
@Override
protected void beginResizing( int direction ) {
desktopManager.get().beginResizingFrame( getFrame(), direction );
@@ -521,7 +565,7 @@ debug*/
int xOnScreen = e.getXOnScreen();
int yOnScreen = e.getYOnScreen();
// Get current window bounds and compute new bounds based them.
// Get current window bounds and compute new bounds based on them.
// This is necessary because window manager may alter window bounds while resizing.
// E.g. when having two monitors with different scale factors and resizing
// a window on first screen to the second screen, then the window manager may
@@ -535,41 +579,72 @@ debug*/
// top
if( resizeDir == N_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR ) {
newBounds.y = yOnScreen - dragTopOffset;
if( limitToParentBounds() && newBounds.y < 0 )
newBounds.y = 0;
newBounds.height += (oldBounds.y - newBounds.y);
}
// bottom
if( resizeDir == S_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR )
if( resizeDir == S_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
newBounds.height = (yOnScreen + dragBottomOffset) - newBounds.y;
if( limitToParentBounds() ) {
int parentHeight = getParentBounds().height;
if( newBounds.y + newBounds.height > parentHeight )
newBounds.height = parentHeight - newBounds.y;
}
}
// left
if( resizeDir == W_RESIZE_CURSOR || resizeDir == NW_RESIZE_CURSOR || resizeDir == SW_RESIZE_CURSOR ) {
newBounds.x = xOnScreen - dragLeftOffset;
if( limitToParentBounds() && newBounds.x < 0 )
newBounds.x = 0;
newBounds.width += (oldBounds.x - newBounds.x);
}
// right
if( resizeDir == E_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR )
if( resizeDir == E_RESIZE_CURSOR || resizeDir == NE_RESIZE_CURSOR || resizeDir == SE_RESIZE_CURSOR ) {
newBounds.width = (xOnScreen + dragRightOffset) - newBounds.x;
if( limitToParentBounds() ) {
int parentWidth = getParentBounds().width;
if( newBounds.x + newBounds.width > parentWidth )
newBounds.width = parentWidth - newBounds.x;
}
}
// apply minimum window size
Dimension minimumSize = honorMinimumSizeOnResize() ? getWindowMinimumSize() : null;
if( minimumSize == null )
minimumSize = UIScale.scale( new Dimension( 150, 50 ) );
if( newBounds.width < minimumSize.width ) {
if( newBounds.x != oldBounds.x )
newBounds.x -= (minimumSize.width - newBounds.width);
newBounds.width = minimumSize.width;
}
if( newBounds.height < minimumSize.height ) {
if( newBounds.y != oldBounds.y )
newBounds.y -= (minimumSize.height - newBounds.height);
newBounds.height = minimumSize.height;
if( newBounds.width < minimumSize.width )
changeWidth( oldBounds, newBounds, minimumSize.width );
if( newBounds.height < minimumSize.height )
changeHeight( oldBounds, newBounds, minimumSize.height );
// apply maximum window size
if( honorMaximumSizeOnResize() ) {
Dimension maximumSize = getWindowMaximumSize();
if( newBounds.width > maximumSize.width )
changeWidth( oldBounds, newBounds, maximumSize.width );
if( newBounds.height > maximumSize.height )
changeHeight( oldBounds, newBounds, maximumSize.height );
}
// set window bounds
if( !newBounds.equals( oldBounds ) )
setWindowBounds( newBounds );
}
private void changeWidth( Rectangle oldBounds, Rectangle newBounds, int width ) {
if( newBounds.x != oldBounds.x )
newBounds.x -= (width - newBounds.width);
newBounds.width = width;
}
private void changeHeight( Rectangle oldBounds, Rectangle newBounds, int height ) {
if( newBounds.y != oldBounds.y )
newBounds.y -= (height - newBounds.height);
newBounds.height = height;
}
}
}

View File

@@ -25,6 +25,8 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
@@ -289,6 +291,7 @@ class FlatWindowsNativeWindowBorder
//---- class WndProc ------------------------------------------------------
private class WndProc
implements PropertyChangeListener
{
// WM_NCHITTEST mouse position codes
private static final int
@@ -313,18 +316,36 @@ class FlatWindowsNativeWindowBorder
// remove the OS window title bar
updateFrame( hwnd, (window instanceof JFrame) ? ((JFrame)window).getExtendedState() : 0 );
// set window background (used when resizing window)
updateWindowBackground();
window.addPropertyChangeListener( "background", this );
}
void uninstall() {
window.removePropertyChangeListener( "background", this );
uninstallImpl( hwnd );
// cleanup
window = null;
}
@Override
public void propertyChange( PropertyChangeEvent e ) {
updateWindowBackground();
}
private void updateWindowBackground() {
Color bg = window.getBackground();
if( bg != null )
setWindowBackground( hwnd, bg.getRed(), bg.getGreen(), bg.getBlue() );
}
private native long installImpl( Window window );
private native void uninstallImpl( long hwnd );
private native void updateFrame( long hwnd, int state );
private native void setWindowBackground( long hwnd, int r, int g, int b );
private native void showWindow( long hwnd, int cmd );
// invoked from native code

View File

@@ -514,6 +514,17 @@ ScrollPane.fillUpperCorner = true
ScrollPane.smoothScrolling = true
#---- SearchField ----
SearchField.searchIconColor = fadeout(Actions.GreyInline,10%,lazy)
SearchField.searchIconHoverColor = fadeout(Actions.GreyInline,30%,lazy)
SearchField.searchIconPressedColor = fadeout(Actions.GreyInline,50%,lazy)
SearchField.clearIconColor = fadeout(Actions.GreyInline,50%,lazy)
SearchField.clearIconHoverColor = $SearchField.clearIconColor
SearchField.clearIconPressedColor = fadeout(Actions.GreyInline,20%,lazy)
#---- Separator ----
Separator.height = 3

View File

@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-rule="evenodd">
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
<rect width="6" height="2" x="5" y="12" fill="#FFF"/>
<rect width="6" height="2" x="5" y="11.5" fill="#FFF"/>
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 326 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#7F8B91" fill-opacity=".5" fill-rule="evenodd" d="M8,1.75 C11.4517797,1.75 14.25,4.54822031 14.25,8 C14.25,11.4517797 11.4517797,14.25 8,14.25 C4.54822031,14.25 1.75,11.4517797 1.75,8 C1.75,4.54822031 4.54822031,1.75 8,1.75 Z M10.5,4.5 L8,7 L5.5,4.5 L4.5,5.5 L7,8 L4.5,10.5 L5.5,11.5 L8,9 L10.5,11.5 L11.5,10.5 L9,8 L11.5,5.5 L10.5,4.5 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 446 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="none" stroke="#7F8B91" stroke-linecap="square" stroke-opacity=".5" d="M5,5 L11,11 M5,11 L11,5"/>
</svg>

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
<polygon fill="#7F8B91" points="10.813 9.75 14 12.938 12.938 14 9.75 10.813"/>
<path fill="#7F8B91" d="M7,2 C9.76142375,2 12,4.23857625 12,7 C12,9.76142375 9.76142375,12 7,12 C4.23857625,12 2,9.76142375 2,7 C2,4.23857625 4.23857625,2 7,2 Z M7,3 C4.790861,3 3,4.790861 3,7 C3,9.209139 4.790861,11 7,11 C9.209139,11 11,9.209139 11,7 C11,4.790861 9.209139,3 7,3 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 526 B

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
<polygon fill="#7F8B91" points="8.813 9.75 12 12.938 10.938 14 7.75 10.813"/>
<path fill="#7F8B91" d="M5,2 C7.76142375,2 10,4.23857625 10,7 C10,9.76142375 7.76142375,12 5,12 C2.23857625,12 0,9.76142375 0,7 C0,4.23857625 2.23857625,2 5,2 Z M5,3 C2.790861,3 1,4.790861 1,7 C1,9.209139 2.790861,11 5,11 C7.209139,11 9,9.209139 9,7 C9,4.790861 7.209139,3 5,3 Z"/>
<polygon fill="#7F8B91" points="11 7 16 7 13.5 10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@@ -34,6 +34,7 @@ import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.extras.components.FlatButton;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
import com.formdev.flatlaf.extras.FlatSVGUtils;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.ui.JBRCustomDecorations;
import com.formdev.flatlaf.util.SystemInfo;
import net.miginfocom.layout.ConstraintParser;
@@ -185,6 +186,8 @@ class DemoFrame
Font font = UIManager.getFont( "defaultFont" );
Font newFont = StyleContext.getDefaultStyleContext().getFont( fontFamily, font.getStyle(), font.getSize() );
// StyleContext.getFont() may return a UIResource, which would cause loosing user scale factor on Windows
newFont = FlatUIUtils.nonUIResource( newFont );
UIManager.put( "defaultFont", newFont );
FlatLaf.updateUI();

View File

@@ -28,6 +28,8 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
@@ -47,6 +49,7 @@ import com.sun.jna.Structure.FieldOrder;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WTypes.LPWSTR;
@@ -282,11 +285,12 @@ public class FlatWindowsNativeWindowBorder
//---- class WndProc ------------------------------------------------------
private class WndProc
implements WindowProc
implements WindowProc, PropertyChangeListener
{
private static final int GWLP_WNDPROC = -4;
private static final int
WM_ERASEBKGND = 0x0014,
WM_NCCALCSIZE = 0x0083,
WM_NCHITTEST = 0x0084,
WM_NCRBUTTONUP = 0x00A5,
@@ -326,6 +330,7 @@ public class FlatWindowsNativeWindowBorder
private final HWND hwnd;
private final BaseTSD.LONG_PTR defaultWndProc;
private int wmSizeWParam = -1;
private HBRUSH background;
private int titleBarHeight;
private Rectangle[] hitTestSpots;
@@ -345,9 +350,15 @@ public class FlatWindowsNativeWindowBorder
// remove the OS window title bar
updateFrame( (window instanceof JFrame) ? ((JFrame)window).getExtendedState() : 0 );
// set window background (used when resizing window)
updateWindowBackground();
window.addPropertyChangeListener( "background", this );
}
void uninstall() {
window.removePropertyChangeListener( "background", this );
// restore original window procedure
if( SystemInfo.isX86_64 )
User32Ex.INSTANCE.SetWindowLongPtr( hwnd, GWLP_WNDPROC, defaultWndProc );
@@ -358,6 +369,8 @@ public class FlatWindowsNativeWindowBorder
updateFrame( 0 );
// cleanup
if( background != null )
GDI32.INSTANCE.DeleteObject( background );
window = null;
}
@@ -382,6 +395,26 @@ public class FlatWindowsNativeWindowBorder
wmSizeWParam = -1;
}
@Override
public void propertyChange( PropertyChangeEvent evt ) {
updateWindowBackground();
}
private void updateWindowBackground() {
Color bg = window.getBackground();
if( bg != null )
setWindowBackground( bg.getRed(), bg.getGreen(), bg.getBlue() );
}
private void setWindowBackground( int r, int g, int b ) {
// delete old background brush
if( background != null )
GDI32.INSTANCE.DeleteObject( background );
// create new background brush
background = GDI32Ex.INSTANCE.CreateSolidBrush( RGB( r, g, b ) );
}
/**
* NOTE: This method is invoked on the AWT-Windows thread (not the AWT-EventQueue thread).
*/
@@ -408,6 +441,9 @@ public class FlatWindowsNativeWindowBorder
wParam = new WPARAM( wmSizeWParam );
break;
case WM_ERASEBKGND:
return WmEraseBkgnd( hwnd, uMsg, wParam, lParam );
case WM_DESTROY:
return WmDestroy( hwnd, uMsg, wParam, lParam );
}
@@ -432,11 +468,30 @@ public class FlatWindowsNativeWindowBorder
// cleanup
windowsMap.remove( window );
if( background != null )
GDI32.INSTANCE.DeleteObject( background );
window = null;
return lResult;
}
/**
* Handle WM_ERASEBKGND
*
* https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd
*/
LRESULT WmEraseBkgnd( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam ) {
if( background == null )
return new LRESULT( 0 );
// fill background
HDC hdc = new HDC( wParam.toPointer() );
RECT rect = new RECT();
User32.INSTANCE.GetClientRect( hwnd, rect );
User32Ex.INSTANCE.FillRect( hdc, rect, background );
return new LRESULT( 1 );
}
/**
* Handle WM_NCCALCSIZE
*
@@ -637,6 +692,13 @@ public class FlatWindowsNativeWindowBorder
return (short) ((lParam.longValue() >> 16) & 0xffff);
}
/**
* Same implementation as RGB(r,g,b) macro in wingdi.h.
*/
private DWORD RGB( int r, int g, int b ) {
return new DWORD( (r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16) );
}
/**
* Opens the window's system menu.
* The system menu is the menu that opens when the user presses Alt+Space or
@@ -690,6 +752,8 @@ public class FlatWindowsNativeWindowBorder
LONG_PTR SetWindowLong( HWND hWnd, int nIndex, LONG_PTR wndProc );
LRESULT CallWindowProc( LONG_PTR lpPrevWndFunc, HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam );
int FillRect( HDC hDC, RECT lprc, HBRUSH hbr );
int GetDpiForWindow( HWND hwnd );
int GetSystemMetricsForDpi( int nIndex, int dpi );
@@ -702,6 +766,16 @@ public class FlatWindowsNativeWindowBorder
BOOL TrackPopupMenu( HMENU hMenu, int uFlags, int x, int y, int nReserved, HWND hWnd, RECT prcRect );
}
//---- interface GDI32Ex --------------------------------------------------
private interface GDI32Ex
extends GDI32
{
GDI32Ex INSTANCE = Native.load( "gdi32", GDI32Ex.class, W32APIOptions.DEFAULT_OPTIONS );
HBRUSH CreateSolidBrush( DWORD color );
}
//---- class NCCALCSIZE_PARAMS --------------------------------------------
@FieldOrder( { "rgrc" } )

View File

@@ -73,8 +73,8 @@ library {
linkerArgs.addAll( toolChain.map {
when( it ) {
is Gcc, is Clang -> listOf( "-l${jawt}", "-lUser32", "-lshell32", "-lAdvAPI32", "-lKernel32" )
is VisualCpp -> listOf( "${jawt}.lib", "User32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "/NODEFAULTLIB" )
is Gcc, is Clang -> listOf( "-l${jawt}", "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32" )
is VisualCpp -> listOf( "${jawt}.lib", "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "/NODEFAULTLIB" )
else -> emptyList()
}
} )

View File

@@ -52,6 +52,13 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
FlatWndProc::updateFrame( reinterpret_cast<HWND>( hwnd ), state );
}
extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_setWindowBackground
( JNIEnv* env, jobject obj, jlong hwnd, jint r, jint g, jint b )
{
FlatWndProc::setWindowBackground( reinterpret_cast<HWND>( hwnd ), r, g, b );
}
extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow
( JNIEnv* env, jobject obj, jlong hwnd, jint cmd )
@@ -80,6 +87,7 @@ FlatWndProc::FlatWndProc() {
hwnd = NULL;
defaultWndProc = NULL;
wmSizeWParam = -1;
background = NULL;
}
HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
@@ -128,6 +136,8 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
// cleanup
env->DeleteGlobalRef( fwp->obj );
if( fwp->background != NULL )
::DeleteObject( fwp->background );
delete fwp;
}
@@ -174,8 +184,23 @@ void FlatWndProc::updateFrame( HWND hwnd, int state ) {
fwp->wmSizeWParam = -1;
}
void FlatWndProc::setWindowBackground( HWND hwnd, int r, int g, int b ) {
FlatWndProc* fwp = (FlatWndProc*) hwndMap->get( hwnd );
if( fwp == NULL )
return;
// delete old background brush
if( fwp->background != NULL )
::DeleteObject( fwp->background );
// create new background brush
fwp->background = ::CreateSolidBrush( RGB( r, g, b ) );
}
LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
FlatWndProc* fwp = (FlatWndProc*) hwndMap->get( hwnd );
if( fwp == NULL )
return 0;
return fwp->WindowProc( hwnd, uMsg, wParam, lParam );
}
@@ -204,12 +229,16 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
wParam = wmSizeWParam;
break;
case WM_ERASEBKGND:
return WmEraseBkgnd( hwnd, uMsg, wParam, lParam );
case WM_DESTROY:
return WmDestroy( hwnd, uMsg, wParam, lParam );
}
return ::CallWindowProc( defaultWndProc, hwnd, uMsg, wParam, lParam );
}
/**
* Handle WM_DESTROY
*
@@ -223,6 +252,8 @@ LRESULT FlatWndProc::WmDestroy( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPara
// cleanup
getEnv()->DeleteGlobalRef( obj );
if( background != NULL )
::DeleteObject( background );
hwndMap->remove( hwnd );
delete this;
@@ -230,6 +261,23 @@ LRESULT FlatWndProc::WmDestroy( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lPara
return ::CallWindowProc( defaultWndProc2, hwnd, uMsg, wParam, lParam );
}
/**
* Handle WM_ERASEBKGND
*
* https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd
*/
LRESULT FlatWndProc::WmEraseBkgnd( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam ) {
if( background == NULL )
return FALSE;
// fill background
HDC hdc = (HDC) wParam;
RECT rect;
::GetClientRect( hwnd, &rect );
::FillRect( hdc, &rect, background );
return TRUE;
}
/**
* Handle WM_NCCALCSIZE
*

View File

@@ -26,6 +26,7 @@ public:
static HWND install( JNIEnv *env, jobject obj, jobject window );
static void uninstall( JNIEnv *env, jobject obj, HWND hwnd );
static void updateFrame( HWND hwnd, int state );
static void setWindowBackground( HWND hwnd, int r, int g, int b );
private:
static int initialized;
@@ -41,6 +42,7 @@ private:
HWND hwnd;
WNDPROC defaultWndProc;
int wmSizeWParam;
HBRUSH background;
FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj );
@@ -48,6 +50,7 @@ private:
static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT WmDestroy( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );
LRESULT WmEraseBkgnd( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );
LRESULT WmNcCalcSize( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );
LRESULT WmNcHitTest( HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam );

View File

@@ -39,6 +39,14 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame
(JNIEnv *, jobject, jlong, jint);
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: setWindowBackground
* Signature: (JIII)V
*/
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_setWindowBackground
(JNIEnv *, jobject, jlong, jint, jint, jint);
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: showWindow

View File

@@ -42,3 +42,18 @@ JXTitledPanel.borderColor = $Button.borderColor
JXTitledPanel.titleBackground = $TaskPane.titleBackgroundGradientStart
JXTitledPanel.titleForeground = $TaskPane.titleForeground
JXTitledPanel.captionInsets = 4,10,4,10
#---- SearchField ----
SearchField.icon = com.formdev.flatlaf.icons.FlatSearchIcon
SearchField.rolloverIcon = lazy(SearchField.icon)
SearchField.pressedIcon = lazy(SearchField.icon)
SearchField.popupIcon = com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon
SearchField.popupRolloverIcon = lazy(SearchField.popupIcon)
SearchField.popupPressedIcon = lazy(SearchField.popupIcon)
SearchField.clearIcon = com.formdev.flatlaf.icons.FlatClearIcon
SearchField.clearRolloverIcon = lazy(SearchField.clearIcon)
SearchField.clearPressedIcon = lazy(SearchField.clearIcon)

View File

@@ -879,6 +879,25 @@ ScrollPane.smoothScrolling true
ScrollPaneUI com.formdev.flatlaf.ui.FlatScrollPaneUI
#---- SearchField ----
SearchField.clearIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearIconColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconHoverColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconPressedColor [lazy] #7f8b91cc 80% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.icon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.popupIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.pressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.rolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.searchIconColor [lazy] #7f8b91e6 90% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconHoverColor [lazy] #7f8b91b3 70% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconPressedColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
#---- Separator ----
Separator.background #3c3f41 javax.swing.plaf.ColorUIResource [UI]

View File

@@ -884,6 +884,25 @@ ScrollPane.smoothScrolling true
ScrollPaneUI com.formdev.flatlaf.ui.FlatScrollPaneUI
#---- SearchField ----
SearchField.clearIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearIconColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconHoverColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconPressedColor [lazy] #7f8b91cc 80% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.icon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.popupIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.pressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.rolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.searchIconColor [lazy] #7f8b91e6 90% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconHoverColor [lazy] #7f8b91b3 70% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconPressedColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
#---- Separator ----
Separator.background #f2f2f2 javax.swing.plaf.ColorUIResource [UI]

View File

@@ -883,6 +883,25 @@ ScrollPane.smoothScrolling true
ScrollPaneUI com.formdev.flatlaf.ui.FlatScrollPaneUI
#---- SearchField ----
SearchField.clearIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearIconColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconHoverColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearIconPressedColor [lazy] #7f8b91cc 80% javax.swing.plaf.ColorUIResource [UI]
SearchField.clearPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.clearRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatClearIcon [UI]
SearchField.icon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.popupIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupPressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.popupRolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon [UI]
SearchField.pressedIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.rolloverIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatSearchIcon [UI]
SearchField.searchIconColor [lazy] #7f8b91e6 90% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconHoverColor [lazy] #7f8b91b3 70% javax.swing.plaf.ColorUIResource [UI]
SearchField.searchIconPressedColor [lazy] #7f8b9180 50% javax.swing.plaf.ColorUIResource [UI]
#---- Separator ----
Separator.background #ccffcc javax.swing.plaf.ColorUIResource [UI]

View File

@@ -89,6 +89,15 @@ public class FlatInternalFrameTest
};
internalFrame.setContentPane( panel );
if( minSizeCheckBox.isSelected() ) {
internalFrame.setMinimumSize( new Dimension( 300, 150 ) );
panel.add( new JLabel( "min 300,150" ) );
}
if( maxSizeCheckBox.isSelected() ) {
internalFrame.setMaximumSize( new Dimension( 400, 200 ) );
panel.add( new JLabel( "max 400,200" ) );
}
if( !palette.getComponentOrientation().isLeftToRight() )
internalFrame.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT );
@@ -123,6 +132,8 @@ public class FlatInternalFrameTest
maximizableCheckBox = new JCheckBox();
iconCheckBox = new FlatTriStateCheckBox();
menuBarCheckBox = new JCheckBox();
minSizeCheckBox = new JCheckBox();
maxSizeCheckBox = new JCheckBox();
titleLabel = new JLabel();
titleField = new JTextField();
createFrameButton = new JButton();
@@ -158,6 +169,8 @@ public class FlatInternalFrameTest
"[fill]0" +
"[]0" +
"[]0" +
"[]0" +
"[]0" +
"[]unrel" +
"[]unrel"));
@@ -189,18 +202,26 @@ public class FlatInternalFrameTest
menuBarCheckBox.setText("Menu Bar");
paletteContentPane.add(menuBarCheckBox, "cell 1 2");
//---- minSizeCheckBox ----
minSizeCheckBox.setText("Minimum size 300,150");
paletteContentPane.add(minSizeCheckBox, "cell 0 3 2 1,alignx left,growx 0");
//---- maxSizeCheckBox ----
maxSizeCheckBox.setText("Maximum size 400,200");
paletteContentPane.add(maxSizeCheckBox, "cell 0 4 2 1,alignx left,growx 0");
//---- titleLabel ----
titleLabel.setText("Frame title:");
paletteContentPane.add(titleLabel, "cell 0 3");
paletteContentPane.add(titleField, "cell 1 3");
paletteContentPane.add(titleLabel, "cell 0 5");
paletteContentPane.add(titleField, "cell 1 5");
//---- createFrameButton ----
createFrameButton.setText("Create Frame");
createFrameButton.addActionListener(e -> createInternalFrame());
paletteContentPane.add(createFrameButton, "cell 1 4,alignx right,growx 0");
paletteContentPane.add(createFrameButton, "cell 1 6,alignx right,growx 0");
}
desktopPane.add(palette, JLayeredPane.PALETTE_LAYER);
palette.setBounds(15, 25, 275, 185);
palette.setBounds(15, 25, 275, 275);
}
add(desktopPane, "cell 0 0,width 600,height 600");
@@ -234,6 +255,8 @@ public class FlatInternalFrameTest
private JCheckBox maximizableCheckBox;
private FlatTriStateCheckBox iconCheckBox;
private JCheckBox menuBarCheckBox;
private JCheckBox minSizeCheckBox;
private JCheckBox maxSizeCheckBox;
private JLabel titleLabel;
private JTextField titleField;
private JButton createFrameButton;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -14,7 +14,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JInternalFrame", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill][fill]"
"$rowConstraints": "[fill]0[]0[]0[]unrel[]unrel"
"$rowConstraints": "[fill]0[]0[]0[]0[]0[]unrel[]unrel"
} ) {
name: "palette"
"visible": true
@@ -62,29 +62,41 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "minSizeCheckBox"
"text": "Minimum size 300,150"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3 2 1,alignx left,growx 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maxSizeCheckBox"
"text": "Maximum size 400,200"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 2 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 3"
"value": "cell 0 5"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "titleField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
"value": "cell 1 5"
} )
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 4,alignx right,growx 0"
"value": "cell 1 6,alignx right,growx 0"
} )
}, new FormLayoutConstraints( null ) {
"x": 15
"y": 25
"width": 275
"height": 185
"height": 275
"layer": 100
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {

View File

@@ -0,0 +1,361 @@
/*
* Copyright 2021 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
*
* https://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.testing;
import java.awt.*;
import java.awt.Point;
import javax.swing.*;
import com.formdev.flatlaf.util.Animator;
import net.miginfocom.swing.*;
/**
* @author Karl Tauber
*/
public class FlatPopupTest
extends FlatTestPanel
{
private Popup popup;
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatTestFrame frame = FlatTestFrame.create( args, "FlatPopupTest" );
frame.showFrame( FlatPopupTest::new );
} );
}
FlatPopupTest() {
initComponents();
}
private void showPopupMenu() {
popupMenu1.show( showPopupMenuButton, 0, showPopupMenuButton.getHeight() );
}
private void showLargePopupMenu() {
popupMenu2.show( showLargePopupMenuButton, 0, showLargePopupMenuButton.getHeight() );
}
private void showPopup() {
showPopup( 0, 0 );
}
private void showPopup( int xoffset, int yoffset ) {
hidePopup();
Point pt = showPopupButton.getLocationOnScreen();
popup = PopupFactory.getSharedInstance().getPopup( showPopupButton, popupPanel,
pt.x + xoffset, pt.y + showPopupButton.getHeight() + yoffset );
popup.show();
}
private void hidePopup() {
if( popup == null )
return;
popup.hide();
popup = null;
}
private void movePopupDown() {
movePopup( 0, 600 );
}
private void movePopupRight() {
movePopup( 600, 0 );
}
private void movePopup( int xoffset, int yoffset ) {
showPopup();
Animator animator = new Animator( 1000, fraction -> {
System.out.println(fraction);
showPopup( (int) (fraction * xoffset), (int) (fraction * yoffset) );
} );
animator.start();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label1 = new JLabel();
label2 = new JLabel();
showPopupMenuButton = new JButton();
showLargePopupMenuButton = new JButton();
showPopupButton = new JButton();
hidePopupButton = new JButton();
movePopupDownButton = new JButton();
movePopuprightButton = new JButton();
label4 = new JLabel();
popupMenu1 = new JPopupMenu();
menuItem1 = new JMenuItem();
menuItem2 = new JMenuItem();
menu1 = new JMenu();
menuItem3 = new JMenuItem();
menuItem4 = new JMenuItem();
popupPanel = new JPanel();
label3 = new JLabel();
popupMenu2 = new JPopupMenu();
menuItem5 = new JMenuItem();
menuItem6 = new JMenuItem();
menuItem7 = new JMenuItem();
menuItem8 = new JMenuItem();
menuItem9 = new JMenuItem();
menuItem10 = new JMenuItem();
menuItem11 = new JMenuItem();
menuItem12 = new JMenuItem();
menuItem13 = new JMenuItem();
menuItem14 = new JMenuItem();
menuItem15 = new JMenuItem();
menuItem16 = new JMenuItem();
menuItem17 = new JMenuItem();
menuItem18 = new JMenuItem();
menuItem19 = new JMenuItem();
menuItem20 = new JMenuItem();
menuItem21 = new JMenuItem();
menu2 = new JMenu();
menuItem22 = new JMenuItem();
menuItem23 = new JMenuItem();
//======== this ========
setLayout(new MigLayout(
"ltr,insets dialog,hidemode 3",
// columns
"[fill]" +
"[fill]" +
"[fill]" +
"[fill]",
// rows
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- label1 ----
label1.setText("Label with light-weight tooltip");
label1.setToolTipText("some tip");
add(label1, "cell 0 0");
//---- label2 ----
label2.setText("Label with heavy-weight tooltip");
label2.setToolTipText("some tip\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25");
add(label2, "cell 0 1");
//---- showPopupMenuButton ----
showPopupMenuButton.setText("show light-weight JPopupMenu");
showPopupMenuButton.addActionListener(e -> showPopupMenu());
add(showPopupMenuButton, "cell 0 2");
//---- showLargePopupMenuButton ----
showLargePopupMenuButton.setText("show heavy-weight JPopupMenu");
showLargePopupMenuButton.addActionListener(e -> showLargePopupMenu());
add(showLargePopupMenuButton, "cell 0 3");
//---- showPopupButton ----
showPopupButton.setText("show medium-weight popup");
showPopupButton.addActionListener(e -> showPopup());
add(showPopupButton, "cell 0 4");
//---- hidePopupButton ----
hidePopupButton.setText("hide");
hidePopupButton.addActionListener(e -> hidePopup());
add(hidePopupButton, "cell 1 4");
//---- movePopupDownButton ----
movePopupDownButton.setText("move down");
movePopupDownButton.addActionListener(e -> movePopupDown());
add(movePopupDownButton, "cell 2 4");
//---- movePopuprightButton ----
movePopuprightButton.setText("move right");
movePopuprightButton.addActionListener(e -> movePopupRight());
add(movePopuprightButton, "cell 3 4");
//---- label4 ----
label4.setText("(switches to heavy-weight when moving outside of window)");
add(label4, "cell 0 5 4 1,alignx right,growx 0");
//======== popupMenu1 ========
{
//---- menuItem1 ----
menuItem1.setText("text");
popupMenu1.add(menuItem1);
//---- menuItem2 ----
menuItem2.setText("text");
popupMenu1.add(menuItem2);
//======== menu1 ========
{
menu1.setText("text");
//---- menuItem3 ----
menuItem3.setText("text");
menu1.add(menuItem3);
//---- menuItem4 ----
menuItem4.setText("text");
menu1.add(menuItem4);
}
popupMenu1.add(menu1);
}
//======== popupPanel ========
{
popupPanel.setBackground(new Color(153, 255, 153));
popupPanel.setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]",
// rows
"[]"));
//---- label3 ----
label3.setText("popup");
popupPanel.add(label3, "cell 0 0");
}
//======== popupMenu2 ========
{
//---- menuItem5 ----
menuItem5.setText("text");
popupMenu2.add(menuItem5);
//---- menuItem6 ----
menuItem6.setText("text");
popupMenu2.add(menuItem6);
//---- menuItem7 ----
menuItem7.setText("text");
popupMenu2.add(menuItem7);
//---- menuItem8 ----
menuItem8.setText("text");
popupMenu2.add(menuItem8);
//---- menuItem9 ----
menuItem9.setText("text");
popupMenu2.add(menuItem9);
//---- menuItem10 ----
menuItem10.setText("text");
popupMenu2.add(menuItem10);
//---- menuItem11 ----
menuItem11.setText("text");
popupMenu2.add(menuItem11);
//---- menuItem12 ----
menuItem12.setText("text");
popupMenu2.add(menuItem12);
//---- menuItem13 ----
menuItem13.setText("text");
popupMenu2.add(menuItem13);
//---- menuItem14 ----
menuItem14.setText("text");
popupMenu2.add(menuItem14);
//---- menuItem15 ----
menuItem15.setText("text");
popupMenu2.add(menuItem15);
//---- menuItem16 ----
menuItem16.setText("text");
popupMenu2.add(menuItem16);
//---- menuItem17 ----
menuItem17.setText("text");
popupMenu2.add(menuItem17);
//---- menuItem18 ----
menuItem18.setText("text");
popupMenu2.add(menuItem18);
//---- menuItem19 ----
menuItem19.setText("text");
popupMenu2.add(menuItem19);
//---- menuItem20 ----
menuItem20.setText("text");
popupMenu2.add(menuItem20);
//---- menuItem21 ----
menuItem21.setText("text");
popupMenu2.add(menuItem21);
//======== menu2 ========
{
menu2.setText("text");
//---- menuItem22 ----
menuItem22.setText("text");
menu2.add(menuItem22);
//---- menuItem23 ----
menuItem23.setText("text");
menu2.add(menuItem23);
}
popupMenu2.add(menu2);
}
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JLabel label1;
private JLabel label2;
private JButton showPopupMenuButton;
private JButton showLargePopupMenuButton;
private JButton showPopupButton;
private JButton hidePopupButton;
private JButton movePopupDownButton;
private JButton movePopuprightButton;
private JLabel label4;
private JPopupMenu popupMenu1;
private JMenuItem menuItem1;
private JMenuItem menuItem2;
private JMenu menu1;
private JMenuItem menuItem3;
private JMenuItem menuItem4;
private JPanel popupPanel;
private JLabel label3;
private JPopupMenu popupMenu2;
private JMenuItem menuItem5;
private JMenuItem menuItem6;
private JMenuItem menuItem7;
private JMenuItem menuItem8;
private JMenuItem menuItem9;
private JMenuItem menuItem10;
private JMenuItem menuItem11;
private JMenuItem menuItem12;
private JMenuItem menuItem13;
private JMenuItem menuItem14;
private JMenuItem menuItem15;
private JMenuItem menuItem16;
private JMenuItem menuItem17;
private JMenuItem menuItem18;
private JMenuItem menuItem19;
private JMenuItem menuItem20;
private JMenuItem menuItem21;
private JMenu menu2;
private JMenuItem menuItem22;
private JMenuItem menuItem23;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,206 @@
JFDML JFormDesigner: "7.0.4.0.360" Java: "16" 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": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[fill][fill][fill][fill]"
"$rowConstraints": "[][][][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "Label with light-weight tooltip"
"toolTipText": "some tip"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "Label with heavy-weight tooltip"
"toolTipText": "some tip\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showPopupMenuButton"
"text": "show light-weight JPopupMenu"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showPopupMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showLargePopupMenuButton"
"text": "show heavy-weight JPopupMenu"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showLargePopupMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "showPopupButton"
"text": "show medium-weight popup"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showPopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "hidePopupButton"
"text": "hide"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hidePopup", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "movePopupDownButton"
"text": "move down"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "movePopupDown", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 4"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "movePopuprightButton"
"text": "move right"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "movePopupRight", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 4"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "(switches to heavy-weight when moving outside of window)"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5 4 1,alignx right,growx 0"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 490, 350 )
} )
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu1"
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem1"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem2"
"text": "text"
} )
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu1"
"text": "text"
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem3"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem4"
"text": "text"
} )
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 5, 395 )
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[]"
} ) {
name: "popupPanel"
"background": new java.awt.Color( 153, 255, 153, 255 )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "popup"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 225, 395 )
"size": new java.awt.Dimension( 200, 200 )
} )
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu2"
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem5"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem6"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem7"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem8"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem9"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem10"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem11"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem12"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem13"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem14"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem15"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem16"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem17"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem18"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem19"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem20"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem21"
"text": "text"
} )
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "menu2"
"text": "text"
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem22"
"text": "text"
} )
add( new FormComponent( "javax.swing.JMenuItem" ) {
name: "menuItem23"
"text": "text"
} )
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 5, 505 )
} )
}
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright 2021 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
*
* https://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.testing;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.demo.DemoPrefs;
import com.formdev.flatlaf.extras.FlatInspector;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.util.SystemInfo;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.MigLayout;
/**
* @author Karl Tauber
*/
public class FlatSingleComponentTest
extends JFrame
{
private static final String PREFS_ROOT_PATH = "/flatlaf-test-single";
private static final String KEY_SCALE_FACTOR = "scaleFactor";
private final JLabel infoLabel;
private JComponent createSingleComponent() {
return new JButton( "hello" );
}
public static void main( String[] args ) {
DemoPrefs.init( PREFS_ROOT_PATH );
// set scale factor
if( System.getProperty( FlatSystemProperties.UI_SCALE ) == null ) {
String scaleFactor = DemoPrefs.getState().get( KEY_SCALE_FACTOR, null );
if( scaleFactor != null )
System.setProperty( FlatSystemProperties.UI_SCALE, scaleFactor );
}
// install inspectors
FlatInspector.install( "ctrl shift alt X" );
FlatUIDefaultsInspector.install( "ctrl shift alt Y" );
// disable animated Laf change
System.setProperty( "flatlaf.animatedLafChange", "false" );
// test loading custom defaults from package
FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.testing.customdefaults" );
// set look and feel
DemoPrefs.setupLaf( args );
// create and show frame
new FlatSingleComponentTest();
}
private FlatSingleComponentTest() {
super( "FlatSingleComponentTest" );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JComponent c = createSingleComponent();
Container contentPane = getContentPane();
contentPane.setLayout( new MigLayout( null, null, "[][grow]") );
contentPane.add( c );
infoLabel = new JLabel();
infoLabel.setEnabled( false );
contentPane.add( infoLabel, "newline, aligny bottom,growy 0" );
// register F1, F2, ... keys to switch to Light, Dark or other LaFs
registerSwitchToLookAndFeel( "F1", FlatLightLaf.class.getName() );
registerSwitchToLookAndFeel( "F2", FlatDarkLaf.class.getName() );
registerSwitchToLookAndFeel( "F3", FlatIntelliJLaf.class.getName() );
registerSwitchToLookAndFeel( "F4", FlatDarculaLaf.class.getName() );
registerSwitchToLookAndFeel( "F8", FlatTestLaf.class.getName() );
if( SystemInfo.isWindows )
registerSwitchToLookAndFeel( "F9", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
else if( SystemInfo.isMacOS )
registerSwitchToLookAndFeel( "F9", "com.apple.laf.AquaLookAndFeel" );
else if( SystemInfo.isLinux )
registerSwitchToLookAndFeel( "F9", "com.sun.java.swing.plaf.gtk.GTKLookAndFeel" );
registerSwitchToLookAndFeel( "F12", MetalLookAndFeel.class.getName() );
registerSwitchToLookAndFeel( "F11", NimbusLookAndFeel.class.getName() );
// register Alt+F1, F2, ... keys to change scale factor
registerScaleFactor( "alt F1", "1" );
registerScaleFactor( "alt F2", "1.25" );
registerScaleFactor( "alt F3", "1.5" );
registerScaleFactor( "alt F4", "1.75" );
registerScaleFactor( "alt F5", "2" );
registerScaleFactor( "alt F6", "2.5" );
registerScaleFactor( "alt F7", "3" );
registerScaleFactor( "alt F8", "3.5" );
registerScaleFactor( "alt F9", "4" );
registerScaleFactor( "alt F10", "5" );
registerScaleFactor( "alt F11", "6" );
registerScaleFactor( "alt F12", null );
// register ESC key to close frame
((JComponent)getContentPane()).registerKeyboardAction(
e -> {
dispose();
},
KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
// update info
addWindowListener( new WindowAdapter() {
@Override
public void windowOpened( WindowEvent e ) {
updateInfo();
}
} );
// update info when moved to another screen
addComponentListener( new ComponentAdapter() {
@Override
public void componentMoved( ComponentEvent e ) {
updateInfo();
}
} );
UIManager.addPropertyChangeListener( e -> {
if( "lookAndFeel".equals( e.getPropertyName() ) ) {
EventQueue.invokeLater( () -> {
// update info because user scale factor may change
updateInfo();
} );
}
} );
UIScale.addPropertyChangeListener( e -> {
// update info because user scale factor may change
updateInfo();
} );
setMinimumSize( UIScale.scale( new Dimension( 300, 150 ) ) );
pack();
setLocationRelativeTo( null );
setVisible( true );
}
private void updateInfo() {
double systemScaleFactor = UIScale.getSystemScaleFactor( getGraphicsConfiguration() );
float userScaleFactor = UIScale.getUserScaleFactor();
infoLabel.setText( " (Java " + System.getProperty( "java.version" )
+ (systemScaleFactor != 1 ? ("; system scale factor " + systemScaleFactor) : "")
+ (userScaleFactor != 1 ? ("; user scale factor " + userScaleFactor) : "")
+ (systemScaleFactor == 1 && userScaleFactor == 1 ? "; no scaling" : "")
+ ")" );
}
private void registerSwitchToLookAndFeel( String keyStrokeStr, String lafClassName ) {
KeyStroke keyStroke = KeyStroke.getKeyStroke( keyStrokeStr );
if( keyStroke == null )
throw new IllegalArgumentException( "Invalid key stroke '" + keyStrokeStr + "'" );
((JComponent)getContentPane()).registerKeyboardAction(
e -> {
applyLookAndFeel( lafClassName );
},
keyStroke,
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
}
private void applyLookAndFeel( String lafClassName ) {
try {
UIManager.setLookAndFeel( lafClassName );
FlatLaf.updateUI();
} catch( Exception ex ) {
ex.printStackTrace();
}
}
private void registerScaleFactor( String keyStrokeStr, String scaleFactor ) {
KeyStroke keyStroke = KeyStroke.getKeyStroke( keyStrokeStr );
if( keyStroke == null )
throw new IllegalArgumentException( "Invalid key stroke '" + keyStrokeStr + "'" );
((JComponent)getContentPane()).registerKeyboardAction(
e -> {
applyScaleFactor( scaleFactor );
},
keyStroke,
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
}
private void applyScaleFactor( String scaleFactor ) {
if( scaleFactor != null ) {
System.setProperty( FlatSystemProperties.UI_SCALE, scaleFactor );
DemoPrefs.getState().put( KEY_SCALE_FACTOR, scaleFactor );
} else {
System.clearProperty( FlatSystemProperties.UI_SCALE );
DemoPrefs.getState().remove( KEY_SCALE_FACTOR );
}
applyLookAndFeel( UIManager.getLookAndFeel().getClass().getName() );
pack();
}
}

View File

@@ -17,6 +17,7 @@
package com.formdev.flatlaf.testing;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import javax.swing.*;
import javax.swing.border.*;
@@ -102,10 +103,18 @@ public class FlatTextComponentsTest
JComboBox<String> comboBox3 = new JComboBox<>();
JLabel spinnerLabel = new JLabel();
JSpinner spinner1 = new JSpinner();
JSpinner spinner2 = new JSpinner();
JSpinner spinner3 = new JSpinner();
JLabel label2 = new JLabel();
JComboBox<String> comboBox2 = new JComboBox<>();
JSpinner spinner2 = new JSpinner();
JLabel label1 = new JLabel();
JComboBox<String> comboBox5 = new JComboBox<>();
JSpinner spinner4 = new JSpinner();
JLabel label3 = new JLabel();
JComboBox<String> comboBox4 = new JComboBox<>();
JSpinner spinner3 = new JSpinner();
JLabel label4 = new JLabel();
JComboBox<String> comboBox6 = new JComboBox<>();
JSpinner spinner5 = new JSpinner();
JPopupMenu popupMenu1 = new JPopupMenu();
JMenuItem cutMenuItem = new JMenuItem();
JMenuItem copyMenuItem = new JMenuItem();
@@ -130,8 +139,12 @@ public class FlatTextComponentsTest
"[50,fill]" +
"[]" +
"[]para" +
"[40]" +
"[40]" +
"[]" +
"[]" +
"[::14]" +
"[::14]" +
"[]" +
"[]"));
@@ -401,23 +414,67 @@ public class FlatTextComponentsTest
spinner1.setName("spinner1");
add(spinner1, "cell 1 7,growx");
//---- spinner2 ----
spinner2.setName("spinner2");
add(spinner2, "cell 1 8,growx,height 40");
//---- spinner3 ----
spinner3.setName("spinner3");
add(spinner3, "cell 1 9,growx,hmax 14");
//---- label2 ----
label2.setText("<html>Large row height:<br>(default pref height)</html>");
label2.setName("label2");
add(label2, "cell 0 8,aligny top,growy 0");
//---- comboBox2 ----
comboBox2.setEditable(true);
comboBox2.setName("comboBox2");
add(comboBox2, "cell 1 10,growx,height 40");
add(comboBox2, "cell 1 8,grow");
//---- spinner2 ----
spinner2.setName("spinner2");
add(spinner2, "cell 1 9,grow");
//---- label1 ----
label1.setText("Large pref height:");
label1.setName("label1");
add(label1, "cell 0 10,aligny top,growy 0");
//---- comboBox5 ----
comboBox5.setPreferredSize(new Dimension(60, 40));
comboBox5.setEditable(true);
comboBox5.setName("comboBox5");
add(comboBox5, "cell 1 10,growx");
//---- spinner4 ----
spinner4.setPreferredSize(new Dimension(60, 40));
spinner4.setName("spinner4");
add(spinner4, "cell 1 11,growx");
//---- label3 ----
label3.setText("<html>Small row height:<br>(default pref height)</html>");
label3.setName("label3");
add(label3, "cell 0 12 1 2,aligny top,growy 0");
//---- comboBox4 ----
comboBox4.setEditable(true);
comboBox4.setName("comboBox4");
add(comboBox4, "cell 1 11,growx,hmax 14");
add(comboBox4, "cell 1 12,growx");
//---- spinner3 ----
spinner3.setName("spinner3");
add(spinner3, "cell 1 13,growx");
//---- label4 ----
label4.setText("Small pref height:");
label4.setName("label4");
add(label4, "cell 0 14 1 2,aligny top,growy 0");
//---- comboBox6 ----
comboBox6.setEditable(true);
comboBox6.setPreferredSize(new Dimension(60, 14));
comboBox6.setMinimumSize(new Dimension(60, 14));
comboBox6.setName("comboBox6");
add(comboBox6, "cell 1 14,growx");
//---- spinner5 ----
spinner5.setMinimumSize(new Dimension(60, 14));
spinner5.setPreferredSize(new Dimension(60, 14));
spinner5.setName("spinner5");
add(spinner5, "cell 1 15,growx,hmax 14");
//======== popupMenu1 ========
{

View File

@@ -10,7 +10,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[][][::100][100,fill][fill]"
"$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]para[][][][]"
"$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]para[40][40][][][::14][::14][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -303,15 +303,11 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 7,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner2"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "<html>Large row height:<br>(default pref height)</html>"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 8,growx,height 40"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner3"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 9,growx,hmax 14"
"value": "cell 0 8,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox2"
@@ -320,7 +316,40 @@ new FormModel {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 10,growx,height 40"
"value": "cell 1 8,grow"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner2"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 9,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "Large pref height:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 10,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox5"
"preferredSize": new java.awt.Dimension( 60, 40 )
"editable": true
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 10,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner4"
"preferredSize": new java.awt.Dimension( 60, 40 )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 11,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "<html>Small row height:<br>(default pref height)</html>"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 12 1 2,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox4"
@@ -329,11 +358,40 @@ new FormModel {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 11,growx,hmax 14"
"value": "cell 1 12,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner3"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 13,growx"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "Small pref height:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 14 1 2,aligny top,growy 0"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "comboBox6"
"editable": true
"preferredSize": new java.awt.Dimension( 60, 14 )
"minimumSize": new java.awt.Dimension( 60, 14 )
auxiliary() {
"JavaCodeGenerator.typeParameters": "String"
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 14,growx"
} )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "spinner5"
"minimumSize": new java.awt.Dimension( 60, 14 )
"preferredSize": new java.awt.Dimension( 60, 14 )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 15,growx,hmax 14"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 530, 580 )
"size": new java.awt.Dimension( 530, 660 )
} )
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
name: "popupMenu1"
@@ -350,7 +408,7 @@ new FormModel {
"text": "Paste"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 680 )
"location": new java.awt.Point( 0, 705 )
"size": new java.awt.Dimension( 91, 87 )
} )
}

View File

@@ -124,6 +124,11 @@ public class FlatSwingXTest
JTextField textField3 = new JTextField();
JLabel label10 = new JLabel();
JTextField textField4 = new JTextField();
JLabel label11 = new JLabel();
JXSearchField xSearchField1 = new JXSearchField();
JXSearchField xSearchField2 = new JXSearchField();
JXSearchField xSearchField3 = new JXSearchField();
JXSearchField xSearchField4 = new JXSearchField();
JButton button1 = new JButton();
JButton button2 = new JButton();
@@ -146,6 +151,8 @@ public class FlatSwingXTest
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[37]"));
//---- label1 ----
@@ -425,6 +432,30 @@ public class FlatSwingXTest
}
add(xTitledPanel2, "cell 3 8,grow");
//---- label11 ----
label11.setText("JXSearchField:");
add(label11, "cell 0 9");
//---- xSearchField1 ----
xSearchField1.setText("abc");
add(xSearchField1, "cell 1 9,growx");
//---- xSearchField2 ----
xSearchField2.setEnabled(false);
xSearchField2.setText("abc");
add(xSearchField2, "cell 2 9,growx");
//---- xSearchField3 ----
xSearchField3.setRecentSearchesSaveKey("flatlaf.swingx.search.recent");
xSearchField3.setText("abc");
add(xSearchField3, "cell 1 10,growx");
//---- xSearchField4 ----
xSearchField4.setRecentSearchesSaveKey("flatlaf.swingx.search.recent");
xSearchField4.setEnabled(false);
xSearchField4.setText("abc");
add(xSearchField4, "cell 2 10,growx");
//---- button1 ----
button1.setText("<");

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left][][][][fill]"
"$rowConstraints": "[]0[][]0[top][][][][][][37]"
"$rowConstraints": "[]0[][]0[top][][][][][][][][37]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -354,6 +354,40 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 8,grow"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label11"
"text": "JXSearchField:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 9"
} )
add( new FormComponent( "org.jdesktop.swingx.JXSearchField" ) {
name: "xSearchField1"
"text": "abc"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 9,growx"
} )
add( new FormComponent( "org.jdesktop.swingx.JXSearchField" ) {
name: "xSearchField2"
"enabled": false
"text": "abc"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 9,growx"
} )
add( new FormComponent( "org.jdesktop.swingx.JXSearchField" ) {
name: "xSearchField3"
"recentSearchesSaveKey": "flatlaf.swingx.search.recent"
"text": "abc"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 10,growx"
} )
add( new FormComponent( "org.jdesktop.swingx.JXSearchField" ) {
name: "xSearchField4"
"recentSearchesSaveKey": "flatlaf.swingx.search.recent"
"enabled": false
"text": "abc"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 10,growx"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 700, 600 )

View File

@@ -650,6 +650,21 @@ ScrollPane.font
ScrollPane.foreground
ScrollPane.smoothScrolling
ScrollPaneUI
SearchField.clearIcon
SearchField.clearIconColor
SearchField.clearIconHoverColor
SearchField.clearIconPressedColor
SearchField.clearPressedIcon
SearchField.clearRolloverIcon
SearchField.icon
SearchField.popupIcon
SearchField.popupPressedIcon
SearchField.popupRolloverIcon
SearchField.pressedIcon
SearchField.rolloverIcon
SearchField.searchIconColor
SearchField.searchIconHoverColor
SearchField.searchIconPressedColor
Separator.background
Separator.foreground
Separator.height