From eca7a92128e2186b626c6061f33d39f6d847b334 Mon Sep 17 00:00:00 2001 From: weisj Date: Thu, 24 Oct 2019 17:18:12 +0200 Subject: [PATCH] More improvements to text rendering. Added easy creation of borders. Signed-off-by: weisj --- .../com/github/weisj/darklaf/DarkLaf.java | 3 + .../components/border/DarkBorders.java | 58 +++++++++++++++++ .../components/border/WeakLineBorder.java | 65 +++++++++++++++++++ .../weisj/darklaf/ui/button/DarkButtonUI.java | 2 + .../darklaf/ui/checkbox/DarkCheckBoxUI.java | 2 +- .../ui/colorchooser/DarkPreviewPanel.java | 3 + .../darklaf/ui/menu/DarkMenuItemUIBase.java | 5 ++ .../weisj/darklaf/ui/menu/DarkMenuUI.java | 5 ++ .../ui/numberingpane/DarkNumberingPaneUI.java | 3 + .../ui/progressbar/DarkProgressBarUI.java | 2 +- .../ui/tabbedpane/DarkTabbedPaneUI.java | 10 +++ src/test/java/TabFrameDemo.java | 11 +++- 12 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/github/weisj/darklaf/components/border/DarkBorders.java create mode 100644 src/main/java/com/github/weisj/darklaf/components/border/WeakLineBorder.java diff --git a/src/main/java/com/github/weisj/darklaf/DarkLaf.java b/src/main/java/com/github/weisj/darklaf/DarkLaf.java index 165a6b6c..e2c86cc0 100644 --- a/src/main/java/com/github/weisj/darklaf/DarkLaf.java +++ b/src/main/java/com/github/weisj/darklaf/DarkLaf.java @@ -23,6 +23,7 @@ */ package com.github.weisj.darklaf; +import com.github.weisj.darklaf.components.border.DarkBorders; import com.github.weisj.darklaf.platform.windows.JNIDecorations; import com.github.weisj.darklaf.theme.Theme; import com.github.weisj.darklaf.ui.menu.DarkPopupMenuUI; @@ -303,6 +304,7 @@ public class DarkLaf extends BasicLookAndFeel implements PropertyChangeListener public void uninitialize() { call("uninitialize"); AppContext context = AppContext.getAppContext(); + UIManager.removePropertyChangeListener(this); synchronized (DarkPopupMenuUI.MOUSE_GRABBER_KEY) { Object grabber = context.get(DarkPopupMenuUI.MOUSE_GRABBER_KEY); if (grabber != null) { @@ -376,6 +378,7 @@ public class DarkLaf extends BasicLookAndFeel implements PropertyChangeListener } UIManager.removePropertyChangeListener(this); } + DarkBorders.update(); } diff --git a/src/main/java/com/github/weisj/darklaf/components/border/DarkBorders.java b/src/main/java/com/github/weisj/darklaf/components/border/DarkBorders.java new file mode 100644 index 00000000..37ce88ce --- /dev/null +++ b/src/main/java/com/github/weisj/darklaf/components/border/DarkBorders.java @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (c) 2019 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.components.border; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.border.Border; +import java.util.Map; +import java.util.WeakHashMap; + +public final class DarkBorders { + + private static final WeakLineBorder KEY = new WeakLineBorder(0, 0, 0, 0); + private static Map lineBorderMap = new WeakHashMap<>(); + + @NotNull + public static Border createLineBorder(final int top, final int left, final int bottom, final int right) { + WeakLineBorder border = null; + KEY.setInsets(top, left, bottom, right); + if (lineBorderMap.containsKey(KEY)) { + border = lineBorderMap.get(KEY); + } + if (border == null) { + border = new WeakLineBorder(top, left, bottom, right); + lineBorderMap.put(KEY, border); + } + border.setColor(UIManager.getColor("border")); + return border; + } + + public static void update() { + for (var border : lineBorderMap.values()) { + border.setColor(UIManager.getColor("border")); + } + } +} diff --git a/src/main/java/com/github/weisj/darklaf/components/border/WeakLineBorder.java b/src/main/java/com/github/weisj/darklaf/components/border/WeakLineBorder.java new file mode 100644 index 00000000..4f03c706 --- /dev/null +++ b/src/main/java/com/github/weisj/darklaf/components/border/WeakLineBorder.java @@ -0,0 +1,65 @@ +/* + * MIT License + * + * Copyright (c) 2019 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.components.border; + +import org.jetbrains.annotations.Contract; + +class WeakLineBorder extends MutableLineBorder { + + private int left; + private int top; + private int bottom; + private int right; + + public WeakLineBorder(final int top, final int left, final int bottom, final int right) { + super(top, left, bottom, right, null); + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + @Override + public int hashCode() { + int result = left; + result = 31 * result + top; + result = 31 * result + bottom; + result = 31 * result + right; + return result; + } + + @Contract(value = "null -> false", pure = true) + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WeakLineBorder that = (WeakLineBorder) o; + + if (left != that.left) return false; + if (top != that.top) return false; + if (bottom != that.bottom) return false; + return right == that.right; + } +} diff --git a/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java b/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java index c4eb61df..35cea140 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java @@ -117,6 +117,7 @@ public class DarkButtonUI extends BasicButtonUI { @Override protected void paintText(@NotNull final Graphics g, final JComponent c, final Rectangle textRect, final String text) { + var config = GraphicsUtil.setupAntialiasing(g); AbstractButton button = (AbstractButton) c; ButtonModel model = button.getModel(); g.setColor(getForeground(button)); @@ -132,6 +133,7 @@ public class DarkButtonUI extends BasicButtonUI { textRect.x + getTextShiftOffset(), textRect.y + metrics.getAscent() + getTextShiftOffset()); } + config.restore(); } protected Color getForeground(@NotNull final AbstractButton button) { diff --git a/src/main/java/com/github/weisj/darklaf/ui/checkbox/DarkCheckBoxUI.java b/src/main/java/com/github/weisj/darklaf/ui/checkbox/DarkCheckBoxUI.java index 1b8f9270..5ca3cd12 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/checkbox/DarkCheckBoxUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/checkbox/DarkCheckBoxUI.java @@ -219,7 +219,7 @@ public class DarkCheckBoxUI extends MetalCheckBoxUI { public static void paintText(@NotNull final Graphics2D g, @NotNull final AbstractButton b, final Rectangle textRect, final String text, final FontMetrics fm, final Color disabledTextColor) { - GraphicsContext context = GraphicsUtil.setupAntialiasing(g, true, false); + GraphicsContext context = GraphicsUtil.setupAntialiasing(g); g.setFont(b.getFont()); View view = (View) b.getClientProperty(BasicHTML.propertyKey); if (view != null) { diff --git a/src/main/java/com/github/weisj/darklaf/ui/colorchooser/DarkPreviewPanel.java b/src/main/java/com/github/weisj/darklaf/ui/colorchooser/DarkPreviewPanel.java index 06763449..24384c92 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/colorchooser/DarkPreviewPanel.java +++ b/src/main/java/com/github/weisj/darklaf/ui/colorchooser/DarkPreviewPanel.java @@ -23,6 +23,7 @@ */ package com.github.weisj.darklaf.ui.colorchooser; +import com.github.weisj.darklaf.util.GraphicsUtil; import org.jetbrains.annotations.NotNull; import sun.swing.SwingUtilities2; @@ -145,6 +146,7 @@ public class DarkPreviewPanel extends JPanel { } private int paintText(@NotNull final Graphics g, final int offsetX) { + var config = GraphicsUtil.setupAntialiasing(g); g.setFont(getFont()); JComponent host = getColorChooser(); if (host == null) { @@ -176,6 +178,7 @@ public class DarkPreviewPanel extends JPanel { SwingUtilities2.drawString(host, g, getSampleText(), textXOffset + (TEXT_GAP / 2), ((height + TEXT_GAP) * 2) + ascent + 2); + config.restore(); return width + TEXT_GAP * 3; } diff --git a/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuItemUIBase.java b/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuItemUIBase.java index 211f83a1..687e7ede 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuItemUIBase.java +++ b/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuItemUIBase.java @@ -24,6 +24,7 @@ package com.github.weisj.darklaf.ui.menu; import com.github.weisj.darklaf.util.DarkUIUtil; +import com.github.weisj.darklaf.util.GraphicsUtil; import com.github.weisj.darklaf.util.LazyActionMap; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -118,6 +119,7 @@ public class DarkMenuItemUIBase extends BasicMenuItemUI { protected void paintText(final Graphics g, @NotNull final MenuItemLayoutHelper lh, final MenuItemLayoutHelper.LayoutResult lr) { + var config = GraphicsUtil.setupAntialiasing(g); if (!lh.getText().isBlank()) { if (lh.getHtmlView() != null) { // Text is HTML @@ -127,10 +129,12 @@ public class DarkMenuItemUIBase extends BasicMenuItemUI { paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText()); } } + config.restore(); } protected void paintAccText(final Graphics g, final MenuItemLayoutHelper lh, final MenuItemLayoutHelper.LayoutResult lr) { + var config = GraphicsUtil.setupAntialiasing(g); rightAlignAccText(lh, lr); if (!lh.getAccText().isBlank()) { ButtonModel model = lh.getMenuItem().getModel(); @@ -166,6 +170,7 @@ public class DarkMenuItemUIBase extends BasicMenuItemUI { lh.getAccFontMetrics().getAscent()); } } + config.restore(); } protected void paintArrowIcon(final Graphics g, @NotNull final MenuItemLayoutHelper lh, diff --git a/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuUI.java b/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuUI.java index 38429886..16f8d02d 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/menu/DarkMenuUI.java @@ -24,6 +24,7 @@ package com.github.weisj.darklaf.ui.menu; import com.github.weisj.darklaf.util.DarkUIUtil; +import com.github.weisj.darklaf.util.GraphicsUtil; import org.jetbrains.annotations.NotNull; import sun.swing.MenuItemLayoutHelper; import sun.swing.SwingUtilities2; @@ -112,6 +113,7 @@ public class DarkMenuUI extends BasicMenuUI { protected void paintText(final Graphics g, @NotNull final MenuItemLayoutHelper lh, final MenuItemLayoutHelper.LayoutResult lr) { + var config = GraphicsUtil.setupAntialiasing(g); if (!lh.getText().isBlank()) { if (lh.getHtmlView() != null) { // Text is HTML @@ -121,10 +123,12 @@ public class DarkMenuUI extends BasicMenuUI { paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText()); } } + config.restore(); } protected void paintAccText(final Graphics g, final MenuItemLayoutHelper lh, final MenuItemLayoutHelper.LayoutResult lr) { + var config = GraphicsUtil.setupAntialiasing(g); rightAlignAccText(lh, lr); if (!lh.getAccText().isBlank()) { ButtonModel model = lh.getMenuItem().getModel(); @@ -160,6 +164,7 @@ public class DarkMenuUI extends BasicMenuUI { lh.getAccFontMetrics().getAscent()); } } + config.restore(); } protected void paintArrowIcon(final Graphics g, @NotNull final MenuItemLayoutHelper lh, diff --git a/src/main/java/com/github/weisj/darklaf/ui/numberingpane/DarkNumberingPaneUI.java b/src/main/java/com/github/weisj/darklaf/ui/numberingpane/DarkNumberingPaneUI.java index ebdffbd8..420fc666 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/numberingpane/DarkNumberingPaneUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/numberingpane/DarkNumberingPaneUI.java @@ -26,6 +26,7 @@ package com.github.weisj.darklaf.ui.numberingpane; import com.github.weisj.darklaf.components.text.LineHighlighter; import com.github.weisj.darklaf.components.text.NumberingPane; import com.github.weisj.darklaf.util.DarkUIUtil; +import com.github.weisj.darklaf.util.GraphicsUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -185,6 +186,7 @@ public class DarkNumberingPaneUI extends ComponentUI { protected void drawNumbering(@NotNull final Graphics g, final int startLine, final int endLine, final int yCur, @NotNull final Element root, final int descent) { + var config = GraphicsUtil.setupAntialiasing(g); g.setColor(numberingPane.getForeground()); int digits = String.valueOf(root.getElementCount()).length(); for (int i = startLine; i <= endLine; i++) { @@ -196,6 +198,7 @@ public class DarkNumberingPaneUI extends ComponentUI { lineRect.y + lineRect.height - descent); } catch (BadLocationException ignored) { } } + config.restore(); } protected void paintIcons(final Graphics g, final int startLine, final int endLine, @NotNull final Element root) { diff --git a/src/main/java/com/github/weisj/darklaf/ui/progressbar/DarkProgressBarUI.java b/src/main/java/com/github/weisj/darklaf/ui/progressbar/DarkProgressBarUI.java index 5d10e05a..e636b3a0 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/progressbar/DarkProgressBarUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/progressbar/DarkProgressBarUI.java @@ -192,11 +192,11 @@ public class DarkProgressBarUI extends BasicProgressBarUI { private void paintString(@NotNull final Graphics2D g, final int x, final int y, final int w, final int h, final int fillStart, final int amountFull) { + var config = GraphicsUtil.setupAntialiasing(g); String progressString = progressBar.getString(); g.setFont(progressBar.getFont()); Point renderLocation = getStringPlacement(g, progressString, x, y, w, h); - var config = GraphicsUtil.setupAntialiasing(g); if (progressBar.getOrientation() == SwingConstants.HORIZONTAL) { g.setColor(getSelectionBackground()); g.drawString(progressString, renderLocation.x, renderLocation.y); diff --git a/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java b/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java index b58043c2..450c83eb 100644 --- a/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java +++ b/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/DarkTabbedPaneUI.java @@ -26,6 +26,7 @@ package com.github.weisj.darklaf.ui.tabbedpane; import com.github.weisj.darklaf.components.uiresource.UIResourceWrapper; import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.GraphicsContext; +import com.github.weisj.darklaf.util.GraphicsUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -761,6 +762,15 @@ public class DarkTabbedPaneUI extends DarkTabbedPaneUIBridge { } } + @Override + protected void paintText(final Graphics g, final int tabPlacement, final Font font, + final FontMetrics metrics, final int tabIndex, final String title, + final Rectangle textRect, final boolean isSelected) { + var config = GraphicsUtil.setupAntialiasing(g); + super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); + config.restore(); + } + public Icon getNewTabIcon() { return newTabIcon; } diff --git a/src/test/java/TabFrameDemo.java b/src/test/java/TabFrameDemo.java index bc7b2f15..a70e4935 100644 --- a/src/test/java/TabFrameDemo.java +++ b/src/test/java/TabFrameDemo.java @@ -1,6 +1,7 @@ import com.github.weisj.darklaf.LafManager; import com.github.weisj.darklaf.components.SelectableTreeNode; import com.github.weisj.darklaf.components.alignment.Alignment; +import com.github.weisj.darklaf.components.border.DarkBorders; import com.github.weisj.darklaf.components.tabframe.JTabFrame; import com.github.weisj.darklaf.components.tabframe.TabbedPopup; import com.github.weisj.darklaf.components.text.NonWrappingEditorPane; @@ -77,7 +78,15 @@ public class TabFrameDemo { */ tabFrame.setAcceleratorAt(1, Alignment.NORTH_WEST, 0); - frame.setContentPane(tabFrame); + var contentPane = new JPanel(new BorderLayout()); + var topPanel = new JPanel(new GridBagLayout()); + topPanel.add(new JButton("I do nothing!"), null); + topPanel.setBorder(DarkBorders.createLineBorder(0, 0, 1, 0)); + + contentPane.add(topPanel, BorderLayout.NORTH); + contentPane.add(tabFrame, BorderLayout.CENTER); + + frame.setContentPane(contentPane); tabFrame.setContent(createTextArea()); frame.pack();