/* * MIT License * * Copyright (c) 2020 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.taskpane; import java.awt.*; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.UIResource; import org.jdesktop.swingx.JXCollapsiblePane; import org.jdesktop.swingx.JXHyperlink; import org.jdesktop.swingx.JXTaskPane; import org.jdesktop.swingx.plaf.metal.MetalTaskPaneUI; import com.github.weisj.darklaf.graphics.PaintUtil; public class DarkTaskPaneUI extends MetalTaskPaneUI { public static final String KEY_COLLAPSED = "collapsed"; protected boolean isCollapsed; protected Color borderColor; protected Icon collapsedIcon; protected Icon openIcon; protected int arc; public static ComponentUI createUI(final JComponent c) { return new DarkTaskPaneUI(); } @Override protected void installDefaults() { borderColor = UIManager.getColor("TaskPane.borderColor"); arc = UIManager.getInt("TaskPane.arc"); collapsedIcon = UIManager.getIcon("TaskPane.collapsed.icon"); openIcon = UIManager.getIcon("TaskPane.open.icon"); super.installDefaults(); } @Override protected Border createPaneBorder() { return new DarkPaneBorder(); } @Override protected void installListeners() { super.installListeners(); group.addPropertyChangeListener(JXCollapsiblePane.ANIMATION_STATE_KEY, e -> isCollapsed = KEY_COLLAPSED.equals(e.getNewValue())); } @Override protected Border createContentPaneBorder() { return new CompoundBorder(new DarkContentPaneBorder(borderColor, arc), BorderFactory.createEmptyBorder(10, 10, 10, 10)); } @Override protected void configure(final JXHyperlink link) { super.configure(link); link.setFocusPainted(false); } @Override protected int getRoundHeight() { return arc; } protected boolean isCollapsed() { if (!group.isAnimated()) return group.isCollapsed(); return isCollapsed; } protected static class DarkContentPaneBorder implements Border, UIResource { protected final Color color; protected final int arc; public DarkContentPaneBorder(final Color color, final int arc) { this.arc = arc; this.color = color; } public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { Rectangle clip = g.getClip().getBounds(); int h = height + arc; g.setClip(clip.x, clip.y, width, h / 2 + 1); g.setColor(color); PaintUtil.drawRect(g, x, y, width, h, 1); if (c.isOpaque()) { g.setColor(c.getBackground()); g.setClip(clip.x, clip.x + h - arc, width, arc); PaintUtil.fillRoundRect((Graphics2D) g, x, y, width, h, arc); } g.setClip(clip.x, clip.y + h / 2, width, h / 2); g.setColor(color); PaintUtil.paintLineBorder((Graphics2D) g, x, y, width, h, arc); g.setClip(clip); } public Insets getBorderInsets(final Component c) { return new Insets(0, 1, 1, 1); } public boolean isBorderOpaque() { return true; } } protected class DarkPaneBorder extends PaneBorder { @Override protected void paintTitleBackground(final JXTaskPane group, final Graphics g2) { Graphics2D g = (Graphics2D) g2; int w = group.getWidth(); int h = group.getHeight(); if (group.isSpecial()) { g.setColor(specialTitleBackground); } else { g.setColor(titleBackgroundGradientStart); } if (isCollapsed()) { PaintUtil.fillRoundRect(g, 0, 0, w, h, getRoundHeight()); g.setColor(borderColor); PaintUtil.paintLineBorder(g, 0, 0, w, h, getRoundHeight()); } else { Rectangle clip = g.getClip().getBounds(); g.setClip(0, 0, w, h / 2 + 1); PaintUtil.fillRoundRect(g, 0, 0, w, h, getRoundHeight()); g.setClip(0, h / 2, w, h / 2); g.fillRect(0, 0, w, h); g.setColor(borderColor); g.setClip(0, 0, w, h / 2); PaintUtil.paintLineBorder(g, 0, 0, w, h, getRoundHeight()); g.setClip(0, h / 2, w, h / 2); PaintUtil.drawRect(g, 0, 0, w, h, 1); g.setClip(clip); } } @Override protected void configureLabel(final JXTaskPane group) { super.configureLabel(group); label.setFont(label.getFont().deriveFont(Font.PLAIN)); } @Override protected void paintExpandedControls(final JXTaskPane group, final Graphics g, final int x, final int y, final int width, final int height) { ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(getPaintColor(group)); if (group.isCollapsed()) { collapsedIcon.paintIcon(group, g, x, y); } else { openIcon.paintIcon(group, g, x, y); } ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } @Override protected boolean isMouseOverBorder() { return true; } } }