diff --git a/build.gradle.kts b/build.gradle.kts index 7d6350ad..76576a21 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ import com.github.vlsi.gradle.publishing.dsl.simplifyXml import com.github.vlsi.gradle.publishing.dsl.versionFromResolution import net.ltgt.gradle.errorprone.errorprone import org.gradle.api.tasks.testing.logging.TestExceptionFormat -import java.util.* +import java.util.Locale plugins { idea @@ -96,7 +96,7 @@ allprojects { github( user = "weisj", repository = "darklaf", - workflow = "libs.yml" + workflow = "libs.yml", ) { branches = listOfNotNull(currentBranch, "master", "v$projectVersion", projectVersion) accessToken = githubAccessToken @@ -188,7 +188,7 @@ allprojects { configure { useInMemoryPgpKeys( project.stringProperty("signing.inMemoryKey")?.replace("#", "\n"), - project.stringProperty("signing.password") + project.stringProperty("signing.password"), ) } } @@ -213,7 +213,7 @@ allprojects { disable( "StringSplitter", "InlineMeSuggester", - "MissingSummary" + "MissingSummary", ) } } @@ -314,16 +314,18 @@ allprojects { description.set( project.description - ?: "A themeable Look and Feel for java swing" + ?: "A themeable Look and Feel for java swing", ) name.set( (project.findProperty("artifact.name") as? String) ?: project.name .replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) - else it.toString() - } - .replace("-", " ") + if (it.isLowerCase()) { + it.titlecase(Locale.getDefault()) + } else { + it.toString() + } + }.replace("-", " "), ) url.set("https://github.com/weisJ/darklaf") organization { diff --git a/core/src/main/java/com/github/weisj/darklaf/components/border/RoundedLineBorder.java b/core/src/main/java/com/github/weisj/darklaf/components/border/RoundedLineBorder.java index db0f0657..731365e9 100644 --- a/core/src/main/java/com/github/weisj/darklaf/components/border/RoundedLineBorder.java +++ b/core/src/main/java/com/github/weisj/darklaf/components/border/RoundedLineBorder.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2023 Jannis Weis + * Copyright (c) 2023-2024 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, @@ -25,8 +25,9 @@ import java.awt.*; import javax.swing.border.Border; import com.github.weisj.darklaf.graphics.PaintUtil; +import com.github.weisj.darklaf.platform.RoundedFrame; -public class RoundedLineBorder implements Border { +public class RoundedLineBorder implements Border, RoundedFrame { private final Color color; private final int arc; @@ -38,6 +39,21 @@ public class RoundedLineBorder implements Border { this.thickness = thickness; } + @Override + public int getRadius() { + return arc; + } + + @Override + public Color getColor() { + return color; + } + + @Override + public int getThickness() { + return thickness; + } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java b/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java index a3fc05b4..135d75f9 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019-2023 Jannis Weis + * Copyright (c) 2019-2024 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, @@ -109,7 +109,6 @@ public class DarkComboPopup extends BasicComboPopup { protected void configurePopup() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); setBorderPainted(true); - setOpaque(false); add(overlayScrollPane); setFocusable(false); setOpaque(true); @@ -117,6 +116,7 @@ public class DarkComboPopup extends BasicComboPopup { @Override public void show() { + setBackground(new Color(list.getBackground().getRGB())); comboBox.firePopupMenuWillBecomeVisible(); setListSelection(comboBox.getSelectedIndex()); Point location = getPopupLocation(); diff --git a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java index af64fdf6..99cd68f5 100644 --- a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java +++ b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/JNIDecorationsMacOS.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019-2022 Jannis Weis + * Copyright (c) 2019-2024 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, @@ -34,6 +34,8 @@ public final class JNIDecorationsMacOS { public static native void installDecorations(final long hwnd); + public static native void installPopup(final long hwnd, final int radius, final int thickness, final int rgb); + public static native void uninstallDecorations(final long hwnd, final boolean fullSizeContent, final boolean transparentTitleBar); diff --git a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java index f85430ea..d0a5b4b1 100644 --- a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java +++ b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/MacOSDecorationsProvider.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019-2022 Jannis Weis + * Copyright (c) 2019-2024 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, @@ -25,8 +25,11 @@ import java.util.Collections; import java.util.List; import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; import com.github.weisj.darklaf.platform.*; +import com.github.weisj.darklaf.platform.macos.ui.MacOSDecorationsUtil; import com.github.weisj.darklaf.platform.macos.ui.MacOSTitlePane; public class MacOSDecorationsProvider implements DecorationsProvider { @@ -58,6 +61,40 @@ public class MacOSDecorationsProvider implements DecorationsProvider { return Collections.singletonList("macos_decorations"); } + @Override + public void installPopupWindow(final Window window) { + if (!window.isDisplayable()) { + window.addNotify(); + } + if (window instanceof RootPaneContainer) { + JRootPane rootPane = ((RootPaneContainer) window).getRootPane(); + Border border = getOutermostBorder((JComponent) rootPane.getContentPane()); + while (border instanceof CompoundBorder) { + border = ((CompoundBorder) border).getOutsideBorder(); + } + if (border instanceof RoundedFrame) { + MacOSDecorationsUtil.installPopupWindow(window, + ((RoundedFrame) border).getRadius(), + ((RoundedFrame) border).getThickness(), + ((RoundedFrame) border).getColor().getRGB()); + window.repaint(); + } + } + } + + private static Border getOutermostBorder(final JComponent component) { + JComponent c = component; + while (c.getComponentCount() == 1 && c.getBorder() == null) { + JComponent child = (JComponent) c.getComponent(0); + if (child.getWidth() == c.getWidth() && child.getHeight() == c.getHeight()) { + c = child; + } else { + break; + } + } + return c.getBorder(); + } + @Override public boolean supportsNativeTitleLabel() { return SystemInfo.isMacOSMojave; diff --git a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSDecorationsUtil.java b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSDecorationsUtil.java index 3375857f..c19c6d1d 100644 --- a/macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSDecorationsUtil.java +++ b/macos/src/main/java/com/github/weisj/darklaf/platform/macos/ui/MacOSDecorationsUtil.java @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2020-2022 Jannis Weis + * Copyright (c) 2020-2024 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, @@ -69,6 +69,11 @@ public final class MacOSDecorationsUtil { rootPane, titleVisible, titleBarHeight, titleFontSize); } + public static void installPopupWindow(final Window window, final int radius, final int thickness, final int rgb) { + long windowHandle = JNIDecorationsMacOS.getComponentPointer(window); + JNIDecorationsMacOS.installPopup(windowHandle, radius, thickness, radius); + } + private static void setFullSizeContent(final long windowHandle, final boolean enabled) { if (enabled) { JNIDecorationsMacOS.installDecorations(windowHandle); diff --git a/macos/src/main/objcpp/Decorations.mm b/macos/src/main/objcpp/Decorations.mm index 67b482fd..b91769ae 100644 --- a/macos/src/main/objcpp/Decorations.mm +++ b/macos/src/main/objcpp/Decorations.mm @@ -156,6 +156,36 @@ JNF_COCOA_ENTER(env); JNF_COCOA_EXIT(env); } +JNIEXPORT void JNICALL +Java_com_github_weisj_darklaf_platform_macos_JNIDecorationsMacOS_installPopup(JNIEnv *env, jclass obj, jlong hwnd, jint radius, jint borderWidth, jint borderColor) { +JNF_COCOA_ENTER(env); + NSWindow *nsWindow = OBJC(hwnd); + [JNF_RunLoop performOnMainThreadWaiting:YES withBlock:^{ + nsWindow.hasShadow = YES; + nsWindow.contentView.wantsLayer = YES; + nsWindow.contentView.layer.cornerRadius = radius; + nsWindow.contentView.layer.masksToBounds = YES; + + nsWindow.backgroundColor = NSColor.clearColor; + nsWindow.opaque = NO; + + nsWindow.contentView.layer.borderWidth = borderWidth; + if( borderWidth > 0 ) { + CGFloat red = ((borderColor >> 16) & 0xff) / 255.; + CGFloat green = ((borderColor >> 8) & 0xff) / 255.; + CGFloat blue = (borderColor & 0xff) / 255.; + CGFloat alpha = ((borderColor >> 24) & 0xff) / 255.; + + nsWindow.contentView.layer.borderColor = [[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] CGColor]; + } + + nsWindow.contentView.needsDisplay = YES; + [nsWindow.contentView.layer removeAllAnimations]; + [nsWindow invalidateShadow]; + }]; +JNF_COCOA_EXIT(env); +} + NSRect join(NSRect r, NSButton* button) { NSRect buttonRect = [button convertRect: [button bounds] toView: nil]; return NSUnionRect(r, buttonRect); diff --git a/platform-base/src/main/java/com/github/weisj/darklaf/platform/RoundedFrame.java b/platform-base/src/main/java/com/github/weisj/darklaf/platform/RoundedFrame.java new file mode 100644 index 00000000..da0a64e4 --- /dev/null +++ b/platform-base/src/main/java/com/github/weisj/darklaf/platform/RoundedFrame.java @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (c) 2024 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; + +import java.awt.*; + +public interface RoundedFrame { + int getRadius(); + + Color getColor(); + + int getThickness(); +}