Compare commits

...

10 Commits
2.0.1 ... 2.0.2

18 changed files with 148 additions and 7 deletions

View File

@@ -1,6 +1,16 @@
FlatLaf Change Log FlatLaf Change Log
================== ==================
## 2.0.2
- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on
HiDPI screens when dragging window partly offscreen and back into screen
bounds. (issue #477)
- Repaint component when setting client property `JComponent.outline` (issue
#480).
- macOS: Fixed NPE when using some icons in main menu items. (issue #483)
## 2.0.1 ## 2.0.1
- Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471; - Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471;

View File

@@ -126,6 +126,8 @@ Buzz
Applications using FlatLaf Applications using FlatLaf
-------------------------- --------------------------
- ![New](images/new.svg) [Ultorg](https://www.ultorg.com/) (**commercial**) - a
visual query system for relational databases
- ![New](images/new.svg) [MooInfo](https://github.com/rememberber/MooInfo) - - ![New](images/new.svg) [MooInfo](https://github.com/rememberber/MooInfo) -
visual implementation of OSHI, to view information about the system and visual implementation of OSHI, to view information about the system and
hardware hardware

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
val releaseVersion = "2.0.1" val releaseVersion = "2.0.2"
val developmentVersion = "2.1-SNAPSHOT" val developmentVersion = "2.1-SNAPSHOT"
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion

View File

@@ -96,8 +96,8 @@ public class FlatHelpButtonIcon
</svg> </svg>
*/ */
boolean enabled = c.isEnabled(); boolean enabled = c == null || c.isEnabled();
boolean focused = FlatUIUtils.isPermanentFocusOwner( c ); boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
float xy = 0.5f; float xy = 0.5f;
float wh = iconSize() - 1; float wh = iconSize() - 1;

View File

@@ -63,7 +63,7 @@ public class FlatMenuArrowIcon
@Override @Override
protected void paintIcon( Component c, Graphics2D g ) { protected void paintIcon( Component c, Graphics2D g ) {
if( !c.getComponentOrientation().isLeftToRight() ) if( c != null && !c.getComponentOrientation().isLeftToRight() )
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. ); g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
g.setColor( getArrowColor( c ) ); g.setColor( getArrowColor( c ) );
@@ -82,7 +82,7 @@ public class FlatMenuArrowIcon
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() ) if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
return selectionForeground; return selectionForeground;
return c.isEnabled() ? arrowColor : disabledArrowColor; return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
} }
protected boolean isUnderlineSelection() { protected boolean isUnderlineSelection() {

View File

@@ -262,6 +262,10 @@ public class FlatButtonUI
b.repaint(); b.repaint();
break; break;
case OUTLINE:
b.repaint();
break;
case STYLE: case STYLE:
case STYLE_CLASS: case STYLE_CLASS:
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) { if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
@@ -569,6 +573,9 @@ public class FlatButtonUI
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor, public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
Color focusedColor, Color hoverColor, Color pressedColor ) Color focusedColor, Color hoverColor, Color pressedColor )
{ {
if( c == null )
return enabledColor;
if( !c.isEnabled() ) if( !c.isEnabled() )
return disabledColor; return disabledColor;

View File

@@ -354,6 +354,7 @@ public class FlatComboBoxUI
break; break;
case COMPONENT_ROUND_RECT: case COMPONENT_ROUND_RECT:
case OUTLINE:
comboBox.repaint(); comboBox.repaint();
break; break;

View File

@@ -291,6 +291,10 @@ public class FlatScrollPaneUI
} }
break; break;
case FlatClientProperties.OUTLINE:
scrollpane.repaint();
break;
case FlatClientProperties.STYLE: case FlatClientProperties.STYLE:
case FlatClientProperties.STYLE_CLASS: case FlatClientProperties.STYLE_CLASS:
installStyle(); installStyle();

View File

@@ -538,6 +538,7 @@ public class FlatSpinnerUI
break; break;
case FlatClientProperties.COMPONENT_ROUND_RECT: case FlatClientProperties.COMPONENT_ROUND_RECT:
case FlatClientProperties.OUTLINE:
spinner.repaint(); spinner.repaint();
break; break;

View File

@@ -232,6 +232,7 @@ public class FlatTextFieldUI
switch( e.getPropertyName() ) { switch( e.getPropertyName() ) {
case PLACEHOLDER_TEXT: case PLACEHOLDER_TEXT:
case COMPONENT_ROUND_RECT: case COMPONENT_ROUND_RECT:
case OUTLINE:
case TEXT_FIELD_PADDING: case TEXT_FIELD_PADDING:
c.repaint(); c.repaint();
break; break;

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2022 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.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.Icon;
import com.formdev.flatlaf.ui.TestUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
class TestFlatIconPaintingNullComponent
{
static Graphics graphics;
@BeforeAll
static void setup() {
TestUtils.setup( false );
graphics = new BufferedImage( 32, 32, BufferedImage.TYPE_INT_ARGB ).getGraphics();
graphics.setColor( Color.white );
}
@AfterAll
static void cleanup() {
TestUtils.cleanup();
graphics = null;
}
@Test
void flatHelpButtonIcon() {
paintWithoutException( new FlatHelpButtonIcon() );
}
@Test
void flatMenuArrowIcon() {
paintWithoutException( new FlatMenuArrowIcon() );
}
@Test
void flatSearchIcon() {
paintWithoutException( new FlatSearchIcon() );
}
private void paintWithoutException( Icon icon ) {
graphics.clearRect( 0, 0, 32, 32 );
assertDoesNotThrow( () -> icon.paintIcon( null, graphics, 0, 0 ) );
}
}

View File

@@ -480,7 +480,7 @@ public class FlatSVGIcon
if( url == null ) { if( url == null ) {
loadFailed = true; loadFailed = true;
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null ); LoggingFacade.INSTANCE.logConfig( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
return; return;
} }

View File

@@ -288,6 +288,7 @@ public class FlatWindowsNativeWindowBorder
private static final int GWLP_WNDPROC = -4; private static final int GWLP_WNDPROC = -4;
private static final int private static final int
WM_MOVE = 0x0003,
WM_ERASEBKGND = 0x0014, WM_ERASEBKGND = 0x0014,
WM_NCCALCSIZE = 0x0083, WM_NCCALCSIZE = 0x0083,
WM_NCHITTEST = 0x0084, WM_NCHITTEST = 0x0084,
@@ -301,6 +302,10 @@ public class FlatWindowsNativeWindowBorder
WM_LBUTTONDOWN = 0x0201, WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202, WM_LBUTTONUP = 0x0202,
WM_MOVING = 0x0216,
WM_ENTERSIZEMOVE = 0x0231,
WM_EXITSIZEMOVE = 0x0232,
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320; WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;
// WM_SIZE wParam // WM_SIZE wParam
@@ -341,6 +346,8 @@ public class FlatWindowsNativeWindowBorder
private final LONG_PTR defaultWndProc; private final LONG_PTR defaultWndProc;
private int wmSizeWParam = -1; private int wmSizeWParam = -1;
private HBRUSH background; private HBRUSH background;
private boolean isMovingOrSizing;
private boolean isMoving;
// Swing coordinates/values may be scaled on a HiDPI screen // Swing coordinates/values may be scaled on a HiDPI screen
private int titleBarHeight; private int titleBarHeight;
@@ -477,7 +484,27 @@ public class FlatWindowsNativeWindowBorder
wParam = new WPARAM( wmSizeWParam ); wParam = new WPARAM( wmSizeWParam );
break; break;
case WM_ENTERSIZEMOVE:
isMovingOrSizing = true;
break;
case WM_EXITSIZEMOVE:
isMovingOrSizing = isMoving = false;
break;
case WM_MOVE:
case WM_MOVING:
if( isMovingOrSizing )
isMoving = true;
break;
case WM_ERASEBKGND: case WM_ERASEBKGND:
// do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+
// when dragging the window partly offscreen and back into the screen bounds
if( isMoving )
return new LRESULT( 0 );
return WmEraseBkgnd( hwnd, uMsg, wParam, lParam ); return WmEraseBkgnd( hwnd, uMsg, wParam, lParam );
case WM_DESTROY: case WM_DESTROY:

View File

@@ -88,6 +88,8 @@ FlatWndProc::FlatWndProc() {
defaultWndProc = NULL; defaultWndProc = NULL;
wmSizeWParam = -1; wmSizeWParam = -1;
background = NULL; background = NULL;
isMovingOrSizing = false;
isMoving = false;
} }
HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) { HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
@@ -250,7 +252,27 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
wParam = wmSizeWParam; wParam = wmSizeWParam;
break; break;
case WM_ENTERSIZEMOVE:
isMovingOrSizing = true;
break;
case WM_EXITSIZEMOVE:
isMovingOrSizing = isMoving = false;
break;
case WM_MOVE:
case WM_MOVING:
if( isMovingOrSizing )
isMoving = true;
break;
case WM_ERASEBKGND: case WM_ERASEBKGND:
// do not erase background while the user is moving the window,
// otherwise there may be rendering artifacts on HiDPI screens with Java 9+
// when dragging the window partly offscreen and back into the screen bounds
if( isMoving )
return FALSE;
return WmEraseBkgnd( hwnd, uMsg, wParam, lParam ); return WmEraseBkgnd( hwnd, uMsg, wParam, lParam );
case WM_DESTROY: case WM_DESTROY:

View File

@@ -43,6 +43,8 @@ private:
WNDPROC defaultWndProc; WNDPROC defaultWndProc;
int wmSizeWParam; int wmSizeWParam;
HBRUSH background; HBRUSH background;
bool isMovingOrSizing;
bool isMoving;
FlatWndProc(); FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj ); static void initIDs( JNIEnv *env, jobject obj );

View File

@@ -162,7 +162,6 @@ public class FlatComponentsTest
((JComponent)c).putClientProperty( FlatClientProperties.OUTLINE, outline ); ((JComponent)c).putClientProperty( FlatClientProperties.OUTLINE, outline );
} ); } );
repaint();
textField1.requestFocusInWindow(); textField1.requestFocusInWindow();
} }