From 6884027ca6de42da5febfd65627a3ead11048ad5 Mon Sep 17 00:00:00 2001 From: Jannis Weis <31143295+weisJ@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:17:56 +0200 Subject: [PATCH] Add convenient method to customize titlebar colors --- .../decorations/DecorationsColorProvider.java | 67 ++++++++++++++++ .../decorations/ExternalLafDecorator.java | 77 +++++++++++++------ 2 files changed, 121 insertions(+), 23 deletions(-) create mode 100644 platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DecorationsColorProvider.java diff --git a/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DecorationsColorProvider.java b/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DecorationsColorProvider.java new file mode 100644 index 00000000..55255db6 --- /dev/null +++ b/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/DecorationsColorProvider.java @@ -0,0 +1,67 @@ +/* + * MIT License + * + * Copyright (c) 2022 Jannis Weis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.github.weisj.darklaf.platform.decorations; + +import java.awt.*; + +import com.github.weisj.darklaf.properties.uiresource.DarkColorUIResource; +import com.github.weisj.darklaf.util.ColorUtil; + +public interface DecorationsColorProvider { + + default void onLafChanged() {} + + default Color borderColor() { + return inactiveForegroundColor(); + } + + Color backgroundColor(); + + default Color hoverBackgroundColor() { + Color background = backgroundColor(); + int brightness = (int) ColorUtil.getPerceivedBrightness(background); + if (brightness >= 125) { + // Darken + return new DarkColorUIResource( + Math.max((int) (background.getRed() * 0.9f), 0), + Math.max((int) (background.getGreen() * 0.9f), 0), + Math.max((int) (background.getBlue() * 0.9f), 0)); + } else { + return background.brighter(); + } + } + + default Color clickBackgroundColor() { + return hoverBackgroundColor(); + } + + Color activeForegroundColor(); + + Color inactiveForegroundColor(); + + default Color windowButtonColor() { + return activeForegroundColor(); + } + + default Color inactiveWindowButtonColor() { + return inactiveForegroundColor(); + } +} diff --git a/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/ExternalLafDecorator.java b/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/ExternalLafDecorator.java index 5f29ccd2..18bfc2d9 100644 --- a/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/ExternalLafDecorator.java +++ b/platform-decorations/src/main/java/com/github/weisj/darklaf/platform/decorations/ExternalLafDecorator.java @@ -37,6 +37,9 @@ public final class ExternalLafDecorator { private final PropertyChangeListener propertyChangeListener; private boolean installed; + private final DecorationsColorProvider fallbackColorProvider = new DefaultDecorationsColorProvider(); + private DecorationsColorProvider colorProvider = fallbackColorProvider; + private ExternalLafDecorator() { decorationsManager = new NativeDecorationsManager(); propertyChangeListener = evt -> { @@ -69,6 +72,13 @@ public final class ExternalLafDecorator { UIManager.removePropertyChangeListener(propertyChangeListener); } + public void setColorProvider(final DecorationsColorProvider colorProvider) { + this.colorProvider = colorProvider; + if (colorProvider == null) { + this.colorProvider = fallbackColorProvider; + } + } + public boolean isInstalled() { return installed; } @@ -81,33 +91,22 @@ public final class ExternalLafDecorator { private void installExtraProperties() { IconLoader.updateThemeStatus(new Object()); + colorProvider.onLafChanged(); Properties props = new Properties(); UIDefaults defaults = UIManager.getDefaults(); - JLabel label = new JLabel(); - label.setOpaque(true); - Color foreground = new DarkColorUIResource(label.getForeground()); - Color background = new DarkColorUIResource(label.getBackground()); - label.setEnabled(false); - Color disabledForeground = new DarkColorUIResource(label.getForeground()); - - putOrCopy("borderSecondary", disabledForeground, props, defaults); - - Color highlight = new DarkColorUIResource( - Math.max((int) (background.getRed() * 0.9f), 0), - Math.max((int) (background.getGreen() * 0.9f), 0), - Math.max((int) (background.getBlue() * 0.9f), 0)); - putOrCopy("hoverHighlight", highlight, props, defaults); - putOrCopy("clickHighlight", highlight, props, defaults); - - putOrCopy("background", background, props, defaults); - putOrCopy("textForeground", foreground, props, defaults); - putOrCopy("textForegroundInactive", foreground, props, defaults); - putOrCopy("textForegroundSecondary", disabledForeground, props, defaults); - - putOrCopy("windowButton", foreground, props, defaults); - putOrCopy("windowButtonDisabled", disabledForeground, props, defaults); + putOrCopy("borderSecondary", colorProvider.borderColor(), props, defaults); + putOrCopy("hoverHighlight", colorProvider.hoverBackgroundColor(), props, defaults); + putOrCopy("clickHighlight", colorProvider.clickBackgroundColor(), props, defaults); + + putOrCopy("background", colorProvider.backgroundColor(), props, defaults); + putOrCopy("textForeground", colorProvider.activeForegroundColor(), props, defaults); + putOrCopy("textForegroundInactive", colorProvider.inactiveForegroundColor(), props, defaults); + putOrCopy("textForegroundSecondary", colorProvider.inactiveForegroundColor(), props, defaults); + + putOrCopy("windowButton", colorProvider.windowButtonColor(), props, defaults); + putOrCopy("windowButtonDisabled", colorProvider.inactiveWindowButtonColor(), props, defaults); putOrCopy("windowCloseHovered", new DarkColorUIResource(Color.WHITE), props, defaults); decorationsManager.loadDecorationProperties(props, defaults); @@ -126,4 +125,36 @@ public final class ExternalLafDecorator { defaults.putAll(props); defaults.put("RootPaneUI", BasicNativeDecorationsRootPaneUI.class.getName()); } + + private static class DefaultDecorationsColorProvider implements DecorationsColorProvider { + + private Color foreground; + private Color background; + private Color disabledForeground; + + @Override + public void onLafChanged() { + JLabel label = new JLabel(); + label.setOpaque(true); + foreground = new DarkColorUIResource(label.getForeground()); + background = new DarkColorUIResource(label.getBackground()); + label.setEnabled(false); + disabledForeground = new DarkColorUIResource(label.getForeground()); + } + + @Override + public Color backgroundColor() { + return background; + } + + @Override + public Color activeForegroundColor() { + return foreground; + } + + @Override + public Color inactiveForegroundColor() { + return disabledForeground; + } + } }