macOS light and dark themes (issue #497)

This commit is contained in:
Karl Tauber
2022-05-09 23:31:21 +02:00
parent bfede219d0
commit b459715cb5
20 changed files with 4039 additions and 43 deletions

2
.gitignore vendored
View File

@@ -9,5 +9,7 @@ out/
*.iml *.iml
*.ipr *.ipr
*.iws *.iws
*.xcuserstate
*.xcworkspacedata
.vs/ .vs/
.vscode/ .vscode/

View File

@@ -87,7 +87,7 @@ tasks {
"action" to "generate", "action" to "generate",
"fileName" to "${project.name}-sigtest.txt", "fileName" to "${project.name}-sigtest.txt",
"classpath" to jar.get().outputs.files.asPath, "classpath" to jar.get().outputs.files.asPath,
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util", "packages" to "com.formdev.flatlaf,com.formdev.flatlaf.themes,com.formdev.flatlaf.util",
"version" to version, "version" to version,
"release" to "1.8", // Java version "release" to "1.8", // Java version
"failonerror" to "true" ) "failonerror" to "true" )

View File

@@ -0,0 +1,68 @@
/*
* 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.themes;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatDarkLaf;
/**
* A Flat LaF that imitates macOS dark look.
* <p>
* The UI defaults are loaded from {@code FlatMacDarkLaf.properties},
* {@code FlatDarkLaf.properties} and {@code FlatLaf.properties}.
*
* @author Karl Tauber
* @since 3
*/
public class FlatMacDarkLaf
extends FlatDarkLaf
{
public static final String NAME = "FlatLaf macOS Dark";
/**
* Sets the application look and feel to this LaF
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
*/
public static boolean setup() {
return setup( new FlatMacDarkLaf() );
}
/**
* Adds this look and feel to the set of available look and feels.
* <p>
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
* to query available LaFs and display them to the user in a combobox.
*/
public static void installLafInfo() {
installLafInfo( NAME, FlatMacDarkLaf.class );
}
@Override
public String getName() {
return NAME;
}
@Override
public String getDescription() {
return "FlatLaf macOS Dark Look and Feel";
}
@Override
public boolean isDark() {
return true;
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.themes;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLightLaf;
/**
* A Flat LaF that imitates macOS light look.
* <p>
* The UI defaults are loaded from {@code FlatMacLightLaf.properties},
* {@code FlatLightLaf.properties} and {@code FlatLaf.properties}.
*
* @author Karl Tauber
* @since 3
*/
public class FlatMacLightLaf
extends FlatLightLaf
{
public static final String NAME = "FlatLaf macOS Light";
/**
* Sets the application look and feel to this LaF
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
*/
public static boolean setup() {
return setup( new FlatMacLightLaf() );
}
/**
* Adds this look and feel to the set of available look and feels.
* <p>
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
* to query available LaFs and display them to the user in a combobox.
*/
public static void installLafInfo() {
installLafInfo( NAME, FlatMacLightLaf.class );
}
@Override
public String getName() {
return NAME;
}
@Override
public String getDescription() {
return "FlatLaf macOS Light Look and Feel";
}
@Override
public boolean isDark() {
return false;
}
}

View File

@@ -49,8 +49,10 @@ public class FlatArrowButton
protected Color pressedBackground; protected Color pressedBackground;
private int arrowWidth = DEFAULT_ARROW_WIDTH; private int arrowWidth = DEFAULT_ARROW_WIDTH;
private float arrowThickness = 1;
private float xOffset = 0; private float xOffset = 0;
private float yOffset = 0; private float yOffset = 0;
private boolean roundBorderAutoXOffset = true;
private boolean hover; private boolean hover;
private boolean pressed; private boolean pressed;
@@ -121,6 +123,16 @@ public class FlatArrowButton
this.arrowWidth = arrowWidth; this.arrowWidth = arrowWidth;
} }
/** @since 3 */
public float getArrowThickness() {
return arrowThickness;
}
/** @since 3 */
public void setArrowThickness( float arrowThickness ) {
this.arrowThickness = arrowThickness;
}
protected boolean isHover() { protected boolean isHover() {
return hover; return hover;
} }
@@ -145,6 +157,16 @@ public class FlatArrowButton
this.yOffset = yOffset; this.yOffset = yOffset;
} }
/** @since 3 */
public boolean isRoundBorderAutoXOffset() {
return roundBorderAutoXOffset;
}
/** @since 3 */
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
}
protected Color deriveBackground( Color background ) { protected Color deriveBackground( Color background ) {
return background; return background;
} }
@@ -208,14 +230,17 @@ public class FlatArrowButton
} }
protected void paintArrow( Graphics2D g ) { protected void paintArrow( Graphics2D g ) {
boolean vert = (direction == NORTH || direction == SOUTH);
int x = 0; int x = 0;
// move arrow for round borders // move arrow for round borders
Container parent = getParent(); if( isRoundBorderAutoXOffset() ) {
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) ) Container parent = getParent();
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 ); boolean vert = (direction == NORTH || direction == SOUTH);
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
}
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, getArrowWidth(), getXOffset(), getYOffset() ); FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
} }
} }

View File

@@ -99,7 +99,7 @@ import com.formdev.flatlaf.util.SystemInfo;
* @uiDefault ComboBox.minimumWidth int * @uiDefault ComboBox.minimumWidth int
* @uiDefault ComboBox.editorColumns int * @uiDefault ComboBox.editorColumns int
* @uiDefault ComboBox.maximumRowCount int * @uiDefault ComboBox.maximumRowCount int
* @uiDefault ComboBox.buttonStyle String auto (default), button or none * @uiDefault ComboBox.buttonStyle String auto (default), button, mac or none
* @uiDefault Component.arrowType String chevron (default) or triangle * @uiDefault Component.arrowType String chevron (default) or triangle
* @uiDefault Component.isIntelliJTheme boolean * @uiDefault Component.isIntelliJTheme boolean
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background * @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
@@ -568,7 +568,9 @@ public class FlatComboBoxUI
int height = c.getHeight(); int height = c.getHeight();
int arrowX = arrowButton.getX(); int arrowX = arrowButton.getX();
int arrowWidth = arrowButton.getWidth(); int arrowWidth = arrowButton.getWidth();
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) && !"none".equals( buttonStyle ); boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) &&
!"none".equals( buttonStyle ) &&
!isMacStyle();
boolean enabled = comboBox.isEnabled(); boolean enabled = comboBox.isEnabled();
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight(); boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
@@ -586,13 +588,21 @@ public class FlatComboBoxUI
: buttonBackground; : buttonBackground;
if( buttonColor != null ) { if( buttonColor != null ) {
g2.setColor( buttonColor ); g2.setColor( buttonColor );
Shape oldClip = g2.getClip(); if( isMacStyle() ) {
if( isLeftToRight ) Insets insets = comboBox.getInsets();
g2.clipRect( arrowX, 0, width - arrowX, height ); int gap = scale( 2 );
else FlatUIUtils.paintComponentBackground( g2, arrowX + gap, insets.top + gap,
g2.clipRect( 0, 0, arrowX + arrowWidth, height ); arrowWidth - (gap * 2), height - insets.top - insets.bottom - (gap * 2),
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc ); 0, arc - focusWidth );
g2.setClip( oldClip ); } else {
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
} }
} }
@@ -731,6 +741,10 @@ public class FlatComboBoxUI
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() ); return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
} }
private boolean isMacStyle() {
return "mac".equals( buttonStyle );
}
/** @since 1.3 */ /** @since 1.3 */
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) { public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
if( comboBox.isEditable() ) { if( comboBox.isEditable() ) {
@@ -751,6 +765,12 @@ public class FlatComboBoxUI
protected FlatComboBoxButton() { protected FlatComboBoxButton() {
this( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor, this( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor,
buttonHoverArrowColor, null, buttonPressedArrowColor, null ); buttonHoverArrowColor, null, buttonPressedArrowColor, null );
if( isMacStyle() ) {
setArrowWidth( 7 );
setArrowThickness( 1.5f );
setRoundBorderAutoXOffset( false );
}
} }
protected FlatComboBoxButton( int direction, String type, Color foreground, Color disabledForeground, protected FlatComboBoxButton( int direction, String type, Color foreground, Color disabledForeground,
@@ -782,6 +802,20 @@ public class FlatComboBoxUI
return super.getArrowColor(); return super.getArrowColor();
} }
@Override
protected void paintArrow( Graphics2D g ) {
if( isMacStyle() && !comboBox.isEditable() ) {
// for style "mac", paint up and down arrows if combobox is not editable
int height = getHeight();
int h = Math.round( height / 2f );
FlatUIUtils.paintArrow( g, 0, 0, getWidth(), h, SwingConstants.NORTH, chevron,
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() + 1.25f );
FlatUIUtils.paintArrow( g, 0, height - h, getWidth(), h, SwingConstants.SOUTH, chevron,
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() - 1.25f );
} else
super.paintArrow( g );
}
} }
//---- class FlatComboPopup ----------------------------------------------- //---- class FlatComboPopup -----------------------------------------------

View File

@@ -65,7 +65,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
* <!-- FlatSpinnerUI --> * <!-- FlatSpinnerUI -->
* *
* @uiDefault Component.minimumWidth int * @uiDefault Component.minimumWidth int
* @uiDefault Spinner.buttonStyle String button (default) or none * @uiDefault Spinner.buttonStyle String button (default), mac or none
* @uiDefault Component.arrowType String chevron (default) or triangle * @uiDefault Component.arrowType String chevron (default) or triangle
* @uiDefault Component.isIntelliJTheme boolean * @uiDefault Component.isIntelliJTheme boolean
* @uiDefault Spinner.disabledBackground Color * @uiDefault Spinner.disabledBackground Color
@@ -347,6 +347,13 @@ public class FlatSpinnerUI
installNextButtonListeners( button ); installNextButtonListeners( button );
else else
installPreviousButtonListeners( button ); installPreviousButtonListeners( button );
if( "mac".equals( buttonStyle ) ) {
button.setArrowWidth( 7 );
button.setArrowThickness( 1.5f );
button.setYOffset( (direction == SwingConstants.NORTH) ? 0.75f : -0.75f );
button.setRoundBorderAutoXOffset( false );
}
return button; return button;
} }
@@ -387,26 +394,50 @@ public class FlatSpinnerUI
int arrowX = button.getX(); int arrowX = button.getX();
int arrowWidth = button.getWidth(); int arrowWidth = button.getWidth();
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight(); boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
// paint arrow buttons background
if( enabled && buttonBackground != null ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow buttons
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor; Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
g2.setColor( separatorColor ); if( "mac".equals( buttonStyle ) ) {
Insets insets = spinner.getInsets();
int gapX = scale( 3 );
int gapY = scale( 1 );
int bx = arrowX + gapX;
int by = insets.top + gapY;
int bw = arrowWidth - (gapX * 2);
int bh = height - insets.top - insets.bottom - (gapY * 2);
float lw = scale( buttonSeparatorWidth ); float lw = scale( buttonSeparatorWidth );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) ); // buttons border
FlatUIUtils.paintOutlinedComponent( g2, bx, by, bw, bh,
0, 0, 0, lw, arc - focusWidth,
null, separatorColor, buttonBackground );
// separator between buttons
if( separatorColor != null ) {
int thickness = scale( 1 );
g2.setColor( separatorColor );
g2.fill( new Rectangle2D.Float( bx + lw, by + ((bh - thickness) / 2f),
bw - (lw * 2), thickness ) );
}
} else {
// paint arrow buttons background
if( enabled && buttonBackground != null ) {
g2.setColor( buttonBackground );
Shape oldClip = g2.getClip();
if( isLeftToRight )
g2.clipRect( arrowX, 0, width - arrowX, height );
else
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
g2.setClip( oldClip );
}
// paint vertical line between value and arrow buttons
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
g2.setColor( separatorColor );
float lw = scale( buttonSeparatorWidth );
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
}
} }
} }

View File

@@ -904,13 +904,15 @@ public class FlatUIUtils
* {@link SwingConstants#WEST} or {@link SwingConstants#EAST}) * {@link SwingConstants#WEST} or {@link SwingConstants#EAST})
* @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow * @param chevron {@code true} for chevron arrow, {@code false} for triangle arrow
* @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled) * @param arrowSize the width of the painted arrow (for vertical direction) (will be scaled)
* @param arrowThickness the thickness of the painted chevron arrow (will be scaled)
* @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled) * @param xOffset an offset added to the x coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
* @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled) * @param yOffset an offset added to the y coordinate of the arrow to paint it out-of-center. Usually zero. (will be scaled)
* *
* @since 1.1 * @since 3
*/ */
public static void paintArrow( Graphics2D g, int x, int y, int width, int height, public static void paintArrow( Graphics2D g, int x, int y, int width, int height,
int direction, boolean chevron, int arrowSize, float xOffset, float yOffset ) int direction, boolean chevron, int arrowSize, float arrowThickness,
float xOffset, float yOffset )
{ {
// compute arrow width/height // compute arrow width/height
// - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5) // - make chevron arrows one pixel smaller because coordinates are based on center of pixels (0.5/0.5)
@@ -944,7 +946,7 @@ debug*/
Shape arrowShape = createArrowShape( direction, chevron, aw, ah ); Shape arrowShape = createArrowShape( direction, chevron, aw, ah );
if( chevron ) { if( chevron ) {
Stroke oldStroke = g.getStroke(); Stroke oldStroke = g.getStroke();
g.setStroke( new BasicStroke( UIScale.scale( 1f ) ) ); g.setStroke( new BasicStroke( UIScale.scale( arrowThickness ) ) );
drawShapePure( g, arrowShape ); drawShapePure( g, arrowShape );
g.setStroke( oldStroke ); g.setStroke( oldStroke );
} else { } else {

View File

@@ -22,6 +22,7 @@ module com.formdev.flatlaf {
exports com.formdev.flatlaf; exports com.formdev.flatlaf;
exports com.formdev.flatlaf.icons; exports com.formdev.flatlaf.icons;
exports com.formdev.flatlaf.themes;
exports com.formdev.flatlaf.ui; exports com.formdev.flatlaf.ui;
exports com.formdev.flatlaf.util; exports com.formdev.flatlaf.util;

View File

@@ -0,0 +1,246 @@
#
# 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.
#
# base theme (light, dark, intellij or darcula); only used by theme editor
@baseTheme = dark
#---- macOS NSColor system colors (in NSColorSpace.deviceRGB) ----
# generated on macOS 12.2 using Xcode and flatlaf-testing/misc/MacOSColorDump.playground
@nsLabelColor = #ffffffd8
@nsSecondaryLabelColor = #ffffff8c
@nsTertiaryLabelColor = #ffffff3f
@nsQuaternaryLabelColor = #ffffff19
@nsSystemRedColor = #ff453a
@nsSystemGreenColor = #32d74b
@nsSystemBlueColor = #0a84ff
@nsSystemOrangeColor = #ff9f0a
@nsSystemYellowColor = #ffd60a
@nsSystemBrownColor = #ac8e68
@nsSystemPinkColor = #ff375f
@nsSystemPurpleColor = #bf5af2
@nsSystemTealColor = #6ac4dc
@nsSystemIndigoColor = #5e5ce6
@nsSystemMintColor = #63e6e2
@nsSystemCyanColor = #5ac8f5
@nsSystemGrayColor = #98989d
@nsLinkColor = #419cff
@nsPlaceholderTextColor = #ffffff3f
@nsWindowFrameTextColor = #ffffffd8
@nsSelectedMenuItemTextColor = #ffffff
@nsAlternateSelectedControlTextColor = #ffffff
@nsHeaderTextColor = #ffffff
@nsSeparatorColor = #ffffff19
@nsGridColor = #1a1a1a
@nsTextColor = #ffffff
@nsTextBackgroundColor = #1e1e1e
@nsSelectedTextColor = #ffffff
@nsSelectedTextBackgroundColor = #3f638b
@nsUnemphasizedSelectedTextBackgroundColor = #464646
@nsUnemphasizedSelectedTextColor = #ffffff
@nsWindowBackgroundColor = #323232
@nsUnderPageBackgroundColor = #282828
@nsControlBackgroundColor = #1e1e1e
@nsSelectedContentBackgroundColor = #0058d0
@nsUnemphasizedSelectedContentBackgroundColor = #464646
@nsFindHighlightColor = #ffff00
@nsControlColor = #ffffff3f
@nsControlTextColor = #ffffffd8
@nsSelectedControlColor = #3f638b
@nsSelectedControlTextColor = #ffffffd8
@nsDisabledControlTextColor = #ffffff3f
@nsKeyboardFocusIndicatorColor = #1aa9ff7f
@nsControlAccentColor = #007aff
# accent colors are:
# @nsSelectedTextBackgroundColor
# @nsSelectedContentBackgroundColor
# @nsSelectedControlColor
# @nsKeyboardFocusIndicatorColor
# @nsControlAccentColor
#---- variables ----
# general background and foreground (text color)
@background = @nsControlBackgroundColor
@foreground = over(@nsControlTextColor,@background)
@disabledForeground = over(@nsSecondaryLabelColor,@background)
# component background
@buttonBackground = over(@nsControlColor,@background)
@componentBackground = darken(over(@nsControlColor,@background),18%)
@disabledComponentBackground = darken(@componentBackground,2%)
@menuBackground = lighten(@background,8%)
# selection
@selectionBackground = @nsSelectedContentBackgroundColor
@selectionForeground = @nsSelectedMenuItemTextColor
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
# text selection
@textSelectionBackground = @nsSelectedTextBackgroundColor
@textSelectionForeground = @nsSelectedTextColor
# accent colors (blueish)
@accentColor = @nsControlAccentColor
@accentFocusColor = @nsKeyboardFocusIndicatorColor
#---- Button ----
Button.arc = 12
Button.borderWidth = 0
Button.disabledBackground = darken($Button.background,10%)
Button.default.borderWidth = 0
Button.toolbar.hoverBackground = #fff1
Button.toolbar.pressedBackground = #fff2
Button.toolbar.selectedBackground = #fff3
#---- CheckBox ----
CheckBox.iconTextGap = 6
CheckBox.arc = 7
CheckBox.icon.focusWidth = null
CheckBox.icon.style = filled
CheckBox.icon[filled].borderWidth = 0
CheckBox.icon[filled].selectedBorderWidth = 0
CheckBox.icon[filled].background = darken(over(@nsControlColor,@background),3%)
CheckBox.icon[filled].disabledBackground = darken($CheckBox.icon[filled].background,10%)
CheckBox.icon[filled].selectedBackground = @accentColor
CheckBox.icon[filled].checkmarkColor = fadeout(@nsSelectedMenuItemTextColor,15%)
CheckBox.icon[filled].disabledCheckmarkColor = darken($CheckBox.icon[filled].checkmarkColor,45%)
CheckBox.icon.focusedBackground = null
#---- ComboBox ----
ComboBox.buttonStyle = mac
ComboBox.background = over(@nsControlColor,@background)
ComboBox.editableBackground = @componentBackground
ComboBox.disabledBackground = @disabledComponentBackground
ComboBox.buttonBackground = @accentColor
ComboBox.buttonArrowColor = @nsSelectedMenuItemTextColor
ComboBox.buttonHoverArrowColor = darken($ComboBox.buttonArrowColor,15%,derived noAutoInverse)
ComboBox.buttonPressedArrowColor = darken($ComboBox.buttonArrowColor,25%,derived noAutoInverse)
ComboBox.popupBackground = @menuBackground
#---- Component ----
Component.focusWidth = 2
Component.innerFocusWidth = 0
Component.innerOutlineWidth = 0
Component.arc = 12
Component.borderColor = @nsSeparatorColor
Component.disabledBorderColor = fadeout(@nsSeparatorColor,5%)
#---- EditorPane ---
EditorPane.disabledBackground = @disabledComponentBackground
EditorPane.selectionBackground = @textSelectionBackground
EditorPane.selectionForeground = @textSelectionForeground
#---- FormattedTextField ---
FormattedTextField.disabledBackground = @disabledComponentBackground
FormattedTextField.selectionBackground = @textSelectionBackground
FormattedTextField.selectionForeground = @textSelectionForeground
#---- PasswordField ---
PasswordField.disabledBackground = @disabledComponentBackground
PasswordField.selectionBackground = @textSelectionBackground
PasswordField.selectionForeground = @textSelectionForeground
#---- ProgressBar ----
ProgressBar.background = lighten(@background,8%)
#---- RadioButton ----
RadioButton.iconTextGap = 6
RadioButton.icon.style = filled
RadioButton.icon[filled].centerDiameter = 6
#---- ScrollBar ----
ScrollBar.width = 12
ScrollBar.track = @componentBackground
ScrollBar.thumb = @buttonBackground
#---- Separator ----
Separator.foreground = @nsSeparatorColor
#---- Slider ----
Slider.trackWidth = 3
Slider.thumbSize = 14,14
Slider.trackColor = lighten(@background,8%)
Slider.thumbColor = lighten($Slider.trackColor,35%)
Slider.disabledTrackColor = darken($Slider.trackColor,4%)
Slider.disabledThumbColor = darken($Slider.thumbColor,32%)
Slider.focusedColor = $Component.focusColor
#---- Spinner ----
Spinner.buttonStyle = mac
Spinner.disabledBackground = @disabledComponentBackground
Spinner.buttonBackground = @buttonBackground
Spinner.buttonSeparatorWidth = 0
#---- TextArea ---
TextArea.disabledBackground = @disabledComponentBackground
TextArea.selectionBackground = @textSelectionBackground
TextArea.selectionForeground = @textSelectionForeground
#---- TextField ----
TextField.disabledBackground = @disabledComponentBackground
TextField.selectionBackground = @textSelectionBackground
TextField.selectionForeground = @textSelectionForeground
#---- TextPane ---
TextPane.disabledBackground = @disabledComponentBackground
TextPane.selectionBackground = @textSelectionBackground
TextPane.selectionForeground = @textSelectionForeground
#---- ToggleButton ----
ToggleButton.disabledBackground = $Button.disabledBackground
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
ToggleButton.toolbar.selectedBackground = #fff3

View File

@@ -0,0 +1,244 @@
#
# 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.
#
# base theme (light, dark, intellij or darcula); only used by theme editor
@baseTheme = light
#---- macOS NSColor system colors (in NSColorSpace.deviceRGB) ----
# generated on macOS 12.2 using Xcode and flatlaf-testing/misc/MacOSColorDump.playground
@nsLabelColor = #000000d8
@nsSecondaryLabelColor = #0000007f
@nsTertiaryLabelColor = #00000042
@nsQuaternaryLabelColor = #00000019
@nsSystemRedColor = #ff3b30
@nsSystemGreenColor = #28cd41
@nsSystemBlueColor = #007aff
@nsSystemOrangeColor = #ff9500
@nsSystemYellowColor = #ffcc00
@nsSystemBrownColor = #a2845e
@nsSystemPinkColor = #ff2d55
@nsSystemPurpleColor = #af52de
@nsSystemTealColor = #59adc4
@nsSystemIndigoColor = #5856d6
@nsSystemMintColor = #00c7be
@nsSystemCyanColor = #55bef0
@nsSystemGrayColor = #8e8e93
@nsLinkColor = #0068da
@nsPlaceholderTextColor = #0000003f
@nsWindowFrameTextColor = #000000d8
@nsSelectedMenuItemTextColor = #ffffff
@nsAlternateSelectedControlTextColor = #ffffff
@nsHeaderTextColor = #000000d8
@nsSeparatorColor = #00000019
@nsGridColor = #e6e6e6
@nsTextColor = #000000
@nsTextBackgroundColor = #ffffff
@nsSelectedTextColor = #000000
@nsSelectedTextBackgroundColor = #b3d7ff
@nsUnemphasizedSelectedTextBackgroundColor = #dcdcdc
@nsUnemphasizedSelectedTextColor = #000000
@nsWindowBackgroundColor = #ececec
@nsUnderPageBackgroundColor = #969696e5
@nsControlBackgroundColor = #ffffff
@nsSelectedContentBackgroundColor = #0063e1
@nsUnemphasizedSelectedContentBackgroundColor = #dcdcdc
@nsFindHighlightColor = #ffff00
@nsControlColor = #ffffff
@nsControlTextColor = #000000d8
@nsSelectedControlColor = #b3d7ff
@nsSelectedControlTextColor = #000000d8
@nsDisabledControlTextColor = #0000003f
@nsKeyboardFocusIndicatorColor = #0067f47f
@nsControlAccentColor = #007aff
# accent colors are:
# @nsSelectedTextBackgroundColor
# @nsSelectedContentBackgroundColor
# @nsSelectedControlColor
# @nsKeyboardFocusIndicatorColor
# @nsControlAccentColor
#---- variables ----
# general background and foreground (text color)
@background = #f6f6f6
@foreground = over(@nsControlTextColor,@background)
@disabledForeground = over(@nsTertiaryLabelColor,@background)
# component background
@buttonBackground = @nsControlColor
@componentBackground = @nsControlColor
@disabledComponentBackground = darken(@componentBackground,2%)
@menuBackground = darken(@background,4%)
# selection
@selectionBackground = @nsSelectedContentBackgroundColor
@selectionForeground = @nsSelectedMenuItemTextColor
@selectionInactiveBackground = @nsUnemphasizedSelectedContentBackgroundColor
# text selection
@textSelectionBackground = @nsSelectedTextBackgroundColor
@textSelectionForeground = @foreground
# accent colors (blueish)
@accentColor = @nsControlAccentColor
@accentFocusColor = @nsKeyboardFocusIndicatorColor
#---- Button ----
Button.arc = 12
Button.disabledBackground = @disabledComponentBackground
Button.focusedBackground = null
Button.default.borderWidth = 1
Button.default.boldText = true
Button.default.background = @accentColor
Button.default.foreground = contrast($Button.default.background, @background, $Button.foreground, 20%)
#---- CheckBox ----
CheckBox.iconTextGap = 6
CheckBox.arc = 7
CheckBox.icon.focusWidth = null
CheckBox.icon.style = filled
CheckBox.icon[filled].borderWidth = 1
CheckBox.icon[filled].selectedBorderWidth = 0
CheckBox.icon[filled].disabledSelectedBorderWidth = 1
CheckBox.icon[filled].background = @nsControlColor
CheckBox.icon[filled].disabledBackground = @disabledComponentBackground
CheckBox.icon[filled].selectedBackground = @accentColor
CheckBox.icon[filled].borderColor = $Component.borderColor
CheckBox.icon[filled].disabledBorderColor = $Component.disabledBorderColor
CheckBox.icon[filled].checkmarkColor = @nsSelectedMenuItemTextColor
CheckBox.icon[filled].disabledCheckmarkColor = darken($CheckBox.icon[filled].checkmarkColor,25%)
CheckBox.icon.focusedBackground = null
#---- ComboBox ----
ComboBox.buttonStyle = mac
ComboBox.disabledBackground = @disabledComponentBackground
ComboBox.buttonBackground = @accentColor
ComboBox.buttonArrowColor = @nsSelectedMenuItemTextColor
ComboBox.buttonHoverArrowColor = darken($ComboBox.buttonArrowColor,15%,derived noAutoInverse)
ComboBox.buttonPressedArrowColor = darken($ComboBox.buttonArrowColor,25%,derived noAutoInverse)
ComboBox.popupBackground = @menuBackground
#---- Component ----
Component.focusWidth = 2
Component.innerFocusWidth = 0
Component.innerOutlineWidth = 0
Component.arc = 12
Component.borderColor = fadein(@nsSeparatorColor,5%)
Component.disabledBorderColor = @nsSeparatorColor
#---- EditorPane ---
EditorPane.disabledBackground = @disabledComponentBackground
EditorPane.selectionBackground = @textSelectionBackground
EditorPane.selectionForeground = @textSelectionForeground
#---- FormattedTextField ---
FormattedTextField.disabledBackground = @disabledComponentBackground
FormattedTextField.selectionBackground = @textSelectionBackground
FormattedTextField.selectionForeground = @textSelectionForeground
#---- PasswordField ---
PasswordField.disabledBackground = @disabledComponentBackground
PasswordField.selectionBackground = @textSelectionBackground
PasswordField.selectionForeground = @textSelectionForeground
#---- ProgressBar ----
ProgressBar.background = darken(@background,5%)
#---- RadioButton ----
RadioButton.iconTextGap = 6
RadioButton.icon.style = filled
RadioButton.icon[filled].centerDiameter = 6
#---- ScrollBar ----
ScrollBar.width = 12
ScrollBar.track = darken(@componentBackground,2%)
ScrollBar.thumb = darken(@componentBackground,24%)
#---- Separator ----
Separator.foreground = @nsSeparatorColor
#---- Slider ----
Slider.trackWidth = 3
Slider.thumbSize = 14,14
Slider.trackColor = darken(@background,7%)
Slider.thumbColor = @componentBackground
Slider.thumbBorderColor = $Component.borderColor
Slider.disabledTrackColor = lighten($Slider.trackColor,3%)
Slider.disabledThumbColor = darken($Slider.thumbColor,3%)
#---- Spinner ----
Spinner.buttonStyle = mac
Spinner.disabledBackground = @disabledComponentBackground
Spinner.buttonArrowColor = @foreground
Spinner.buttonHoverArrowColor = lighten($Spinner.buttonArrowColor,20%,derived noAutoInverse)
Spinner.buttonPressedArrowColor = lighten($Spinner.buttonArrowColor,30%,derived noAutoInverse)
#---- TextArea ---
TextArea.disabledBackground = @disabledComponentBackground
TextArea.selectionBackground = @textSelectionBackground
TextArea.selectionForeground = @textSelectionForeground
#---- TextField ----
TextField.disabledBackground = @disabledComponentBackground
TextField.selectionBackground = @textSelectionBackground
TextField.selectionForeground = @textSelectionForeground
#---- TextPane ---
TextPane.disabledBackground = @disabledComponentBackground
TextPane.selectionBackground = @textSelectionBackground
TextPane.selectionForeground = @textSelectionForeground
#---- ToggleButton ----
ToggleButton.disabledBackground = $Button.disabledBackground

View File

@@ -54,6 +54,7 @@ import com.formdev.flatlaf.IntelliJTheme;
import com.formdev.flatlaf.demo.DemoPrefs; import com.formdev.flatlaf.demo.DemoPrefs;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.formdev.flatlaf.extras.FlatSVGIcon; import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.themes.*;
import com.formdev.flatlaf.ui.FlatListUI; import com.formdev.flatlaf.ui.FlatListUI;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.StringUtils;
@@ -185,6 +186,11 @@ public class IJThemesPanel
if( showDark ) if( showDark )
themes.add( new IJThemeInfo( "FlatLaf Darcula", null, true, null, null, null, null, null, FlatDarculaLaf.class.getName() ) ); themes.add( new IJThemeInfo( "FlatLaf Darcula", null, true, null, null, null, null, null, FlatDarculaLaf.class.getName() ) );
if( showLight )
themes.add( new IJThemeInfo( "FlatLaf macOS Light", null, false, null, null, null, null, null, FlatMacLightLaf.class.getName() ) );
if( showDark )
themes.add( new IJThemeInfo( "FlatLaf macOS Dark", null, true, null, null, null, null, null, FlatMacDarkLaf.class.getName() ) );
// add themes from directory // add themes from directory
categories.put( themes.size(), "Current Directory" ); categories.put( themes.size(), "Current Directory" );
themes.addAll( themesManager.moreThemes ); themes.addAll( themesManager.moreThemes );

View File

@@ -121,7 +121,7 @@ public class FlatJideSplitButtonUI
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g ); Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
FlatUIUtils.paintArrow( (Graphics2D) g, r.x, r.y, r.width, r.height, FlatUIUtils.paintArrow( (Graphics2D) g, r.x, r.y, r.width, r.height,
SwingConstants.SOUTH, FlatUIUtils.isChevron( arrowType ), 6, 0, 0 ); SwingConstants.SOUTH, FlatUIUtils.isChevron( arrowType ), 6, 1, 0, 0 );
FlatUIUtils.resetRenderingHints( g, oldRenderingHints ); FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
} }
} }

View File

@@ -891,7 +891,7 @@ public class FlatJideTabbedPaneUI
g.setColor( button.isEnabled() ? foreground : disabledForeground ); g.setColor( button.isEnabled() ? foreground : disabledForeground );
FlatUIUtils.paintArrow( (Graphics2D) g, FlatUIUtils.paintArrow( (Graphics2D) g,
0, 0, button.getWidth(), button.getHeight(), 0, 0, button.getWidth(), button.getHeight(),
direction, FlatUIUtils.isChevron( arrowType ), 10, 0, 0 ); direction, FlatUIUtils.isChevron( arrowType ), 10, 1, 0, 0 );
FlatUIUtils.resetRenderingHints( g, oldRenderingHints ); FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
import Cocoa
func colorToHex( color: NSColor ) -> String {
return String( format: (color.alphaComponent != 1 ? "#%02x%02x%02x%02x" : "#%02x%02x%02x"),
Int( 255 * color.redComponent ),
Int( 255 * color.greenComponent ),
Int( 255 * color.blueComponent ),
Int( 255 * color.alphaComponent ) )
}
func printColorHex( color: NSColor, space: NSColorSpace ) {
print( "@ns", color.colorNameComponent.prefix(1).capitalized, color.colorNameComponent.dropFirst(),
" = ", colorToHex( color: color.usingColorSpace( space )! ),
separator: "" )
}
func printColorsHex( space: NSColorSpace ) {
print( "#----", space, "----" )
// order is the same as in Xcode color chooser (Color Palettes > Developer)
printColorHex( color: NSColor.labelColor, space: space )
printColorHex( color: NSColor.secondaryLabelColor, space: space )
printColorHex( color: NSColor.tertiaryLabelColor, space: space )
printColorHex( color: NSColor.quaternaryLabelColor, space: space )
printColorHex( color: NSColor.systemRed, space: space )
printColorHex( color: NSColor.systemGreen, space: space )
printColorHex( color: NSColor.systemBlue, space: space )
printColorHex( color: NSColor.systemOrange, space: space )
printColorHex( color: NSColor.systemYellow, space: space )
printColorHex( color: NSColor.systemBrown, space: space )
printColorHex( color: NSColor.systemPink, space: space )
printColorHex( color: NSColor.systemPurple, space: space )
printColorHex( color: NSColor.systemTeal, space: space )
printColorHex( color: NSColor.systemIndigo, space: space )
printColorHex( color: NSColor.systemMint, space: space )
printColorHex( color: NSColor.systemCyan, space: space )
printColorHex( color: NSColor.systemGray, space: space )
printColorHex( color: NSColor.linkColor, space: space )
printColorHex( color: NSColor.placeholderTextColor, space: space )
printColorHex( color: NSColor.windowFrameTextColor, space: space )
printColorHex( color: NSColor.selectedMenuItemTextColor, space: space )
printColorHex( color: NSColor.alternateSelectedControlTextColor, space: space )
printColorHex( color: NSColor.headerTextColor, space: space )
printColorHex( color: NSColor.separatorColor, space: space )
printColorHex( color: NSColor.gridColor, space: space )
printColorHex( color: NSColor.textColor, space: space )
printColorHex( color: NSColor.textBackgroundColor, space: space )
printColorHex( color: NSColor.selectedTextColor, space: space )
printColorHex( color: NSColor.selectedTextBackgroundColor, space: space )
printColorHex( color: NSColor.unemphasizedSelectedTextBackgroundColor, space: space )
printColorHex( color: NSColor.unemphasizedSelectedTextColor, space: space )
printColorHex( color: NSColor.windowBackgroundColor, space: space )
printColorHex( color: NSColor.underPageBackgroundColor, space: space )
printColorHex( color: NSColor.controlBackgroundColor, space: space )
printColorHex( color: NSColor.selectedContentBackgroundColor, space: space )
printColorHex( color: NSColor.unemphasizedSelectedContentBackgroundColor, space: space )
print( "# alternatingContentBackgroundColors =", NSColor.alternatingContentBackgroundColors )
printColorHex( color: NSColor.findHighlightColor, space: space )
printColorHex( color: NSColor.controlColor, space: space )
printColorHex( color: NSColor.controlTextColor, space: space )
printColorHex( color: NSColor.selectedControlColor, space: space )
printColorHex( color: NSColor.selectedControlTextColor, space: space )
printColorHex( color: NSColor.disabledControlTextColor, space: space )
printColorHex( color: NSColor.keyboardFocusIndicatorColor, space: space )
printColorHex( color: NSColor.controlAccentColor, space: space )
print()
}
// printColorsHex( space: NSColorSpace.genericRGB )
printColorsHex( space: NSColorSpace.deviceRGB )

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos'>
<timeline fileName='timeline.xctimeline'/>
</playground>

View File

@@ -1077,7 +1077,7 @@ public class FlatPaintingTest
private void paintArrow( Graphics2D g, int width, int height ) { private void paintArrow( Graphics2D g, int width, int height ) {
FlatUIUtils.paintArrow( g, 0, 0, width, height, FlatUIUtils.paintArrow( g, 0, 0, width, height,
direction, chevron, arrowSize, xOffset, yOffset ); direction, chevron, arrowSize, 1, xOffset, yOffset );
if( button ) { if( button ) {
FlatArrowButton arrowButton = new FlatArrowButton( direction, FlatArrowButton arrowButton = new FlatArrowButton( direction,

View File

@@ -65,6 +65,7 @@ import javax.swing.plaf.basic.BasicLookAndFeel;
import com.formdev.flatlaf.*; import com.formdev.flatlaf.*;
import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes; import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes;
import com.formdev.flatlaf.testing.FlatTestLaf; import com.formdev.flatlaf.testing.FlatTestLaf;
import com.formdev.flatlaf.themes.*;
import com.formdev.flatlaf.ui.FlatLineBorder; import com.formdev.flatlaf.ui.FlatLineBorder;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction; import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
@@ -103,6 +104,9 @@ public class UIDefaultsDump
if( SystemInfo.isWindows ) { if( SystemInfo.isWindows ) {
dump( FlatIntelliJLaf.class.getName(), dir, false ); dump( FlatIntelliJLaf.class.getName(), dir, false );
dump( FlatDarculaLaf.class.getName(), dir, false ); dump( FlatDarculaLaf.class.getName(), dir, false );
dump( FlatMacLightLaf.class.getName(), dir, false );
dump( FlatMacDarkLaf.class.getName(), dir, false );
} }
dump( FlatTestLaf.class.getName(), dir, false ); dump( FlatTestLaf.class.getName(), dir, false );
@@ -463,9 +467,9 @@ public class UIDefaultsDump
if( resolvedColor != color && resolvedColor.getRGB() != color.getRGB() ) { if( resolvedColor != color && resolvedColor.getRGB() != color.getRGB() ) {
if( !isIntelliJTheme ) { if( !isIntelliJTheme ) {
System.err.println( "Key '" + key + "': derived colors not equal" ); System.err.println( "Key '" + key + "': derived colors not equal" );
System.err.println( " Default color: " + dumpColorHexAndHSL( color ) ); System.err.println( " Default color: " + dumpColorHexAndHSL( color ) );
System.err.println( " Resolved color: " + dumpColorHexAndHSL( resolvedColor ) ); System.err.println( " Resolved color: " + dumpColorHexAndHSL( resolvedColor ) );
System.err.println( " Base of resolved color: " + dumpColorHexAndHSL( retBaseColor[0] ) ); System.err.println( " Base color: " + dumpColorHexAndHSL( retBaseColor[0] ) );
} }
out.printf( "%s / ", out.printf( "%s / ",