Browse Source

ScrollBar: Use rounded scrollbars on Windows 11

spotless
Jannis Weis 3 years ago
parent
commit
4c28099ec9
No known key found for this signature in database
GPG Key ID: 7C9D8D4B558049AB
  1. 9
      core/src/main/java/com/github/weisj/darklaf/task/ThemeDefaultsInitTask.java
  2. 102
      core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkMacScrollBarUI.java
  3. 136
      core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkRoundedScrollBarUI.java
  4. 43
      core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkWindows11ScrollBarUI.java
  5. 31
      core/src/main/resources/com/github/weisj/darklaf/platform/windows11.properties
  6. 4
      utils/src/main/java/com/github/weisj/darklaf/util/SystemInfo.java

9
core/src/main/java/com/github/weisj/darklaf/task/ThemeDefaultsInitTask.java

@ -25,6 +25,7 @@ import java.awt.*;
import java.util.HashMap;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Consumer;
import javax.swing.*;
@ -155,9 +156,13 @@ public class ThemeDefaultsInitTask implements DefaultsInitTask {
private void initPlatformProperties(final Theme currentTheme, final UIDefaults defaults, final Properties uiProps) {
IconResolver iconResolver = DarkUIUtil.iconResolver();
PropertyLoader.putProperties(
PropertyLoader.loadProperties(DarkLaf.class, getOsName(), "platform/"),
Consumer<String> osPlatformLoader = osName -> PropertyLoader.putProperties(
PropertyLoader.loadProperties(DarkLaf.class, osName, "platform/"),
uiProps, defaults, iconResolver);
osPlatformLoader.accept(getOsName());
if (SystemInfo.isWindows11OrGreater) {
osPlatformLoader.accept("windows11");
}
currentTheme.customizePlatformProperties(uiProps, defaults, iconResolver);
}

102
core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkMacScrollBarUI.java

@ -21,19 +21,10 @@
*/
package com.github.weisj.darklaf.ui.scrollpane;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import com.github.weisj.darklaf.graphics.LegacyAnimator;
import com.github.weisj.darklaf.util.graphics.GraphicsContext;
import com.github.weisj.darklaf.util.graphics.GraphicsUtil;
public class DarkMacScrollBarUI extends DarkScrollBarUI {
private boolean hideScrollBar;
public class DarkMacScrollBarUI extends DarkRoundedScrollBarUI {
public static ComponentUI createUI(final JComponent c) {
return new DarkMacScrollBarUI();
@ -46,94 +37,7 @@ public class DarkMacScrollBarUI extends DarkScrollBarUI {
}
@Override
protected void paintTrack(final Graphics g, final JComponent c, final Rectangle bounds) {}
@Override
protected void paintMaxiThumb(final Graphics2D g, final Rectangle rect) {
GraphicsContext context = GraphicsUtil.setupStrokePainting(g);
g.setComposite(COMPOSITE.derive(thumbAlpha));
boolean horizontal = scrollbar.getOrientation() == JScrollBar.HORIZONTAL;
int ins = 2;
RoundRectangle2D roundRect = new RoundRectangle2D.Float();
int width = rect.width - 2 * ins;
int height = rect.height - 2 * ins;
int x = rect.x + ins;
int y = rect.y + ins;
if (hideScrollBar) {
float animationState = scrollBarListener.getTrackState();
if (horizontal) {
int newHeight = Math.round(height * animationState);
y += height - newHeight;
height = newHeight;
} else {
int newWidth = Math.round(width * animationState);
if (scrollbar.getComponentOrientation().isLeftToRight()) {
x += width - newWidth;
}
width = newWidth;
}
}
int arc = horizontal ? height : width;
roundRect.setRoundRect(x, y, width, height, arc, arc);
g.setColor(getThumbColor());
g.fill(roundRect);
g.setColor(getThumbBorderColor());
g.draw(roundRect);
context.restore();
}
@Override
protected DarkScrollBarListener<DarkMacScrollBarUI> createScrollBarListener() {
return new MacScrollBarListener(scrollbar, this);
}
private static class MacScrollBarListener extends DarkScrollBarListener<DarkMacScrollBarUI> {
private final Timer hideTimer;
public MacScrollBarListener(final JScrollBar scrollbar, final DarkMacScrollBarUI ui) {
super(scrollbar, ui);
int hideDelay = getTrackFadeOutDelay();
hideTimer = new Timer(hideDelay, e -> {
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, scrollbar);
mouseOverTrack = scrollbar.contains(p);
resetTrackAnimator();
});
hideTimer.setRepeats(false);
}
@Override
protected boolean animateTrackOnScroll(final JScrollBar scrollbar) {
return ui.hideScrollBar;
}
@Override
protected LegacyAnimator createTrackFadeinAnimator() {
return ui.hideScrollBar ? super.createTrackFadeinAnimator() : null;
}
@Override
protected LegacyAnimator createTrackFadeoutAnimator() {
return ui.hideScrollBar ? super.createTrackFadeoutAnimator() : null;
}
@Override
protected int getTrackFadeOutDelay() {
return UIManager.getInt("ScrollBar.macos.hideDelay");
}
@Override
protected void runOnScrollTrackAnimation() {
super.runOnScrollTrackAnimation();
hideTimer.stop();
hideTimer.start();
}
@Override
protected void resetTrackAnimator() {
hideTimer.stop();
super.resetTrackAnimator();
}
protected int getTrackFadeOutDelay() {
return UIManager.getInt("ScrollBar.macos.hideDelay");
}
}

136
core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkRoundedScrollBarUI.java

@ -0,0 +1,136 @@
/*
* MIT License
*
* Copyright (c) 2021 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.ui.scrollpane;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
import com.github.weisj.darklaf.graphics.LegacyAnimator;
import com.github.weisj.darklaf.util.graphics.GraphicsContext;
import com.github.weisj.darklaf.util.graphics.GraphicsUtil;
public abstract class DarkRoundedScrollBarUI extends DarkScrollBarUI {
protected boolean hideScrollBar = false;
@Override
protected void installDefaults() {
super.installDefaults();
hideScrollBar = UIManager.getBoolean("ScrollBar.macos.hideScrollBar");
}
protected abstract int getTrackFadeOutDelay();
@Override
protected void paintTrack(final Graphics g, final JComponent c, final Rectangle bounds) {}
@Override
protected void paintMaxiThumb(final Graphics2D g, final Rectangle rect) {
GraphicsContext context = GraphicsUtil.setupStrokePainting(g);
g.setComposite(COMPOSITE.derive(thumbAlpha));
boolean horizontal = scrollbar.getOrientation() == JScrollBar.HORIZONTAL;
int ins = 2;
RoundRectangle2D roundRect = new RoundRectangle2D.Float();
int width = rect.width - 2 * ins;
int height = rect.height - 2 * ins;
int x = rect.x + ins;
int y = rect.y + ins;
if (hideScrollBar) {
float animationState = scrollBarListener.getTrackState();
if (horizontal) {
int newHeight = Math.round(height * animationState);
y += height - newHeight;
height = newHeight;
} else {
int newWidth = Math.round(width * animationState);
if (scrollbar.getComponentOrientation().isLeftToRight()) {
x += width - newWidth;
}
width = newWidth;
}
}
int arc = horizontal ? height : width;
roundRect.setRoundRect(x, y, width, height, arc, arc);
g.setColor(getThumbColor());
g.fill(roundRect);
g.setColor(getThumbBorderColor());
g.draw(roundRect);
context.restore();
}
@Override
protected DarkScrollBarListener<DarkRoundedScrollBarUI> createScrollBarListener() {
return new RoundedScrollBarListener(scrollbar, this);
}
private static class RoundedScrollBarListener extends DarkScrollBarListener<DarkRoundedScrollBarUI> {
private final Timer hideTimer;
public RoundedScrollBarListener(final JScrollBar scrollbar, final DarkRoundedScrollBarUI ui) {
super(scrollbar, ui);
int hideDelay = getTrackFadeOutDelay();
hideTimer = new Timer(hideDelay, e -> {
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, scrollbar);
mouseOverTrack = scrollbar.contains(p);
resetTrackAnimator();
});
hideTimer.setRepeats(false);
}
@Override
protected boolean animateTrackOnScroll(final JScrollBar scrollbar) {
return ui.hideScrollBar;
}
@Override
protected LegacyAnimator createTrackFadeinAnimator() {
return ui.hideScrollBar ? super.createTrackFadeinAnimator() : null;
}
@Override
protected LegacyAnimator createTrackFadeoutAnimator() {
return ui.hideScrollBar ? super.createTrackFadeoutAnimator() : null;
}
@Override
protected int getTrackFadeOutDelay() {
return ui.getTrackFadeOutDelay();
}
@Override
protected void runOnScrollTrackAnimation() {
super.runOnScrollTrackAnimation();
hideTimer.stop();
hideTimer.start();
}
@Override
protected void resetTrackAnimator() {
hideTimer.stop();
super.resetTrackAnimator();
}
}
}

43
core/src/main/java/com/github/weisj/darklaf/ui/scrollpane/DarkWindows11ScrollBarUI.java

@ -0,0 +1,43 @@
/*
* MIT License
*
* Copyright (c) 2021 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.ui.scrollpane;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
public class DarkWindows11ScrollBarUI extends DarkRoundedScrollBarUI {
public static ComponentUI createUI(final JComponent c) {
return new DarkWindows11ScrollBarUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
hideScrollBar = UIManager.getBoolean("ScrollBar.windows11.hideScrollBar");
}
@Override
protected int getTrackFadeOutDelay() {
return UIManager.getInt("ScrollBar.windows11.hideDelay");
}
}

31
core/src/main/resources/com/github/weisj/darklaf/platform/windows11.properties

@ -0,0 +1,31 @@
#
# MIT License
#
# Copyright (c) 2021 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.
#
#
# suppress inspection "UnusedProperty" for whole file
#
ScrollBarUI = com.github.weisj.darklaf.ui.scrollpane.DarkWindows11ScrollBarUI
ScrollBar.smallWidth = 10
ScrollBar.width = 12
ScrollBar.windows11.hideScrollBar = false
ScrollBar.windows11.hideDelay = 1200

4
utils/src/main/java/com/github/weisj/darklaf/util/SystemInfo.java

@ -69,6 +69,7 @@ public final class SystemInfo {
public static final boolean isMacOSMojave;
public static final boolean isMacOSCatalina;
public static final boolean isMacOSYosemite;
public static final boolean isWindows11OrGreater;
public static final boolean isWindows10OrGreater;
public static final boolean isWindows7;
public static final boolean isWindowsVista;
@ -96,8 +97,7 @@ public final class SystemInfo {
isMacOSYosemite = isMacOSCatalina || (isMac && isOsVersionAtLeast("10.10"));
isWindows10OrGreater = isWindows && isOsVersionAtLeast("10.0");
System.out.println(OS_VERSION);
System.out.println(OS_NAME);
isWindows11OrGreater = isWindows && _OS_NAME.contains("windows 11");
isWindows7 = isWindows10OrGreater || (isWindows && isOsVersionAtLeast("6.1"));
isWindowsVista = isWindows7 || (isWindows && isOsVersionAtLeast("6.0"));

Loading…
Cancel
Save