diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowAbstractIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowAbstractIcon.java new file mode 100644 index 00000000..15a8d6ab --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowAbstractIcon.java @@ -0,0 +1,76 @@ +/* + * Copyright 2020 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.Dimension; +import java.awt.Graphics2D; +import javax.swing.UIManager; +import com.formdev.flatlaf.ui.FlatButtonUI; +import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.HiDPIUtils; + +/** + * Base class for window icons. + * + * @uiDefault TitlePane.buttonSize Dimension + * @uiDefault TitlePane.buttonHoverBackground Color + * @uiDefault TitlePane.buttonPressedBackground Color + * + * @author Karl Tauber + */ +public abstract class FlatWindowAbstractIcon + extends FlatAbstractIcon +{ + private final Color hoverBackground; + private final Color pressedBackground; + + public FlatWindowAbstractIcon() { + this( UIManager.getDimension( "TitlePane.buttonSize" ), + UIManager.getColor( "TitlePane.buttonHoverBackground" ), + UIManager.getColor( "TitlePane.buttonPressedBackground" ) ); + } + + public FlatWindowAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) { + super( size.width, size.height, null ); + this.hoverBackground = hoverBackground; + this.pressedBackground = pressedBackground; + } + + @Override + protected void paintIcon( Component c, Graphics2D g ) { + paintBackground( c, g ); + + g.setColor( getForeground( c ) ); + HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x ); + } + + protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ); + + protected void paintBackground( Component c, Graphics2D g ) { + Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground ); + if( background != null ) { + g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) ); + g.fillRect( 0, 0, width, height ); + } + } + + protected Color getForeground( Component c ) { + return c.getForeground(); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowCloseIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowCloseIcon.java new file mode 100644 index 00000000..f4bdc5ca --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowCloseIcon.java @@ -0,0 +1,70 @@ +/* + * Copyright 2020 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.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import javax.swing.UIManager; +import com.formdev.flatlaf.ui.FlatButtonUI; + +/** + * "close" icon for windows (frames and dialogs). + * + * @uiDefault TitlePane.closeHoverBackground Color + * @uiDefault TitlePane.closePressedBackground Color + * @uiDefault TitlePane.closeHoverForeground Color + * @uiDefault TitlePane.closePressedForeground Color + * + * @author Karl Tauber + */ +public class FlatWindowCloseIcon + extends FlatWindowAbstractIcon +{ + private final Color hoverForeground = UIManager.getColor( "TitlePane.closeHoverForeground" ); + private final Color pressedForeground = UIManager.getColor( "TitlePane.closePressedForeground" ); + + public FlatWindowCloseIcon() { + super( UIManager.getDimension( "TitlePane.buttonSize" ), + UIManager.getColor( "TitlePane.closeHoverBackground" ), + UIManager.getColor( "TitlePane.closePressedBackground" ) ); + } + + @Override + protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { + int iwh = (int) (10 * scaleFactor); + int ix = x + ((width - iwh) / 2); + int iy = y + ((height - iwh) / 2); + int ix2 = ix + iwh - 1; + int iy2 = iy + iwh - 1; + int thickness = (int) scaleFactor; + + Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD ); + path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false ); + path.append( new Line2D.Float( ix, iy2, ix2, iy ), false ); + g.setStroke( new BasicStroke( thickness ) ); + g.draw( path ); + } + + @Override + protected Color getForeground( Component c ) { + return FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowIconifyIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowIconifyIcon.java new file mode 100644 index 00000000..54cab7d7 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowIconifyIcon.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 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.Graphics2D; + +/** + * "iconify" icon for windows (frames and dialogs). + * + * @author Karl Tauber + */ +public class FlatWindowIconifyIcon + extends FlatWindowAbstractIcon +{ + public FlatWindowIconifyIcon() { + } + + @Override + protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { + int iw = (int) (10 * scaleFactor); + int ih = (int) scaleFactor; + int ix = x + ((width - iw) / 2); + int iy = y + ((height - ih) / 2); + + g.fillRect( ix, iy, iw, ih ); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowMaximizeIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowMaximizeIcon.java new file mode 100644 index 00000000..5035d43d --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowMaximizeIcon.java @@ -0,0 +1,42 @@ +/* + * Copyright 2020 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.Graphics2D; +import com.formdev.flatlaf.ui.FlatUIUtils; + +/** + * "maximize" icon for windows (frames and dialogs). + * + * @author Karl Tauber + */ +public class FlatWindowMaximizeIcon + extends FlatWindowAbstractIcon +{ + public FlatWindowMaximizeIcon() { + } + + @Override + protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { + int iwh = (int) (10 * scaleFactor); + int ix = x + ((width - iwh) / 2); + int iy = y + ((height - iwh) / 2); + int thickness = (int) scaleFactor; + + g.fill( FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) ); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowRestoreIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowRestoreIcon.java new file mode 100644 index 00000000..b62087ef --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatWindowRestoreIcon.java @@ -0,0 +1,55 @@ +/* + * Copyright 2020 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.Graphics2D; +import java.awt.geom.Area; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import com.formdev.flatlaf.ui.FlatUIUtils; + +/** + * "restore" icon for windows (frames and dialogs). + * + * @author Karl Tauber + */ +public class FlatWindowRestoreIcon + extends FlatWindowAbstractIcon +{ + public FlatWindowRestoreIcon() { + } + + @Override + protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) { + int iwh = (int) (10 * scaleFactor); + int ix = x + ((width - iwh) / 2); + int iy = y + ((height - iwh) / 2); + int thickness = (int) scaleFactor; + + int rwh = (int) (8 * scaleFactor); + int ro2 = iwh - rwh; + + Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness ); + Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness ); + + Area area = new Area( r1 ); + area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) ); + g.fill( area ); + + g.fill( r2 ); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java index 568d9594..bf7eadea 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java @@ -56,7 +56,7 @@ import javax.swing.UIManager; * @uiDefault TitlePane.closeIcon Icon * @uiDefault TitlePane.iconifyIcon Icon * @uiDefault TitlePane.maximizeIcon Icon - * @uiDefault TitlePane.minimizeIcon Icon + * @uiDefault TitlePane.restoreIcon Icon * * @author Karl Tauber */ @@ -109,7 +109,7 @@ class FlatTitlePane private void createButtons() { iconifyButton = createButton( "TitlePane.iconifyIcon", "Iconify", e -> iconify() ); maximizeButton = createButton( "TitlePane.maximizeIcon", "Maximize", e -> maximize() ); - restoreButton = createButton( "TitlePane.minimizeIcon", "Restore", e -> restore() ); + restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() ); closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() ); buttonPanel = new JPanel(); @@ -141,8 +141,17 @@ class FlatTitlePane } private void activeChanged( boolean active ) { - setBackground( active ? activeBackground : inactiveBackground ); - titleLabel.setForeground( FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground ) ); + Color background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground ); + Color foreground = FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground ); + + setBackground( background ); + titleLabel.setForeground( foreground ); + + // this is necessary because hover/pressed colors are derived from background color + iconifyButton.setBackground( background ); + maximizeButton.setBackground( background ); + restoreButton.setBackground( background ); + closeButton.setBackground( background ); } private void frameStateChanged() { diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties index a3f6ad8f..4eeadea6 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties @@ -266,6 +266,12 @@ TableHeader.separatorColor=lighten($TableHeader.background,10%) TableHeader.bottomSeparatorColor=$TableHeader.separatorColor +#---- TitlePane ---- + +TitlePane.buttonHoverBackground=lighten($TitlePane.background,10%,derived) +TitlePane.buttonPressedBackground=lighten($TitlePane.background,20%,derived) + + #---- ToggleButton ---- ToggleButton.selectedBackground=lighten($ToggleButton.background,10%,derived) diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 5b6f4d2a..e545d990 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -579,16 +579,22 @@ TitledBorder.border=1,1,1,1,$Separator.foreground TitlePane.iconSize=16,16 TitlePane.iconMargins=3,8,3,0 TitlePane.titleMargins=3,8,3,8 -TitlePane.closeIcon=$InternalFrame.closeIcon -TitlePane.iconifyIcon=$InternalFrame.iconifyIcon -TitlePane.maximizeIcon=$InternalFrame.maximizeIcon -TitlePane.minimizeIcon=$InternalFrame.minimizeIcon +TitlePane.buttonSize=44,30 +TitlePane.closeIcon=com.formdev.flatlaf.icons.FlatWindowCloseIcon +TitlePane.iconifyIcon=com.formdev.flatlaf.icons.FlatWindowIconifyIcon +TitlePane.maximizeIcon=com.formdev.flatlaf.icons.FlatWindowMaximizeIcon +TitlePane.restoreIcon=com.formdev.flatlaf.icons.FlatWindowRestoreIcon TitlePane.background=$MenuBar.background TitlePane.inactiveBackground=$TitlePane.background TitlePane.foreground=@foreground TitlePane.inactiveForeground=@disabledText +TitlePane.closeHoverBackground=#e81123 +TitlePane.closePressedBackground=rgba($TitlePane.closeHoverBackground,60%) +TitlePane.closeHoverForeground=#fff +TitlePane.closePressedForeground=#fff + #---- ToggleButton ---- diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties index 938997ea..8982df4d 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -273,6 +273,12 @@ TableHeader.separatorColor=darken($TableHeader.background,10%) TableHeader.bottomSeparatorColor=$TableHeader.separatorColor +#---- TitlePane ---- + +TitlePane.buttonHoverBackground=darken($TitlePane.background,10%,derived) +TitlePane.buttonPressedBackground=darken($TitlePane.background,20%,derived) + + #---- ToggleButton ---- ToggleButton.selectedBackground=darken($ToggleButton.background,20%,derived) diff --git a/flatlaf-testing/Windows 10 decorations.png b/flatlaf-testing/Windows 10 decorations.png new file mode 100644 index 00000000..04af6c4c Binary files /dev/null and b/flatlaf-testing/Windows 10 decorations.png differ