From 7d6f7a24f346df7e1b007fb8b01aa958aae6f4ad Mon Sep 17 00:00:00 2001 From: weisj Date: Wed, 9 Oct 2019 23:15:16 +0200 Subject: [PATCH] Ported ProgressBarUI --- .../ui/progressbar/DarkProgressBarBorder.java | 9 + .../ui/progressbar/DarkProgressBarUI.java | 298 ++++++++++++++++++ .../darklaf/ui/tooltip/DarkTooltipUI.java | 2 +- .../com/weis/darklaf/util/DarkUIUtil.java | 10 + .../properties/ui/progressBar.properties | 19 +- .../theme/darcula/darcula_defaults.properties | 12 +- src/test/java/UIDemo.java | 30 +- 7 files changed, 368 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarBorder.java create mode 100644 src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarUI.java diff --git a/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarBorder.java b/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarBorder.java new file mode 100644 index 00000000..f4bbe800 --- /dev/null +++ b/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarBorder.java @@ -0,0 +1,9 @@ +package com.weis.darklaf.ui.progressbar; + +import javax.swing.plaf.BorderUIResource; + +public class DarkProgressBarBorder extends BorderUIResource.EmptyBorderUIResource { + public DarkProgressBarBorder() { + super(0, 0, 0, 0); + } +} diff --git a/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarUI.java b/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarUI.java new file mode 100644 index 00000000..23d808fd --- /dev/null +++ b/src/main/java/com/weis/darklaf/ui/progressbar/DarkProgressBarUI.java @@ -0,0 +1,298 @@ +package com.weis.darklaf.ui.progressbar; + +import com.weis.darklaf.util.DarkUIUtil; +import com.weis.darklaf.util.GraphicsUtil; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicProgressBarUI; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +/** + * @author Konstantin Bulenkov + */ +public class DarkProgressBarUI extends BasicProgressBarUI { + + @NotNull + @Contract("_ -> new") + public static ComponentUI createUI(final JComponent c) { + return new DarkProgressBarUI(); + } + + private Color trackColor; + private Color progressColor; + private Color indeterminateStartColor; + private Color indeterminateEndColor; + + private Color failedColor; + private Color failedEndColor; + private Color passedColor; + private Color passedEndColor; + + private static final int CYCLE_TIME_DEFAULT = 800; + private static final int REPAINT_INTERVAL_DEFAULT = 50; + + private static final int CYCLE_TIME_SIMPLIFIED = 1000; + private static final int REPAINT_INTERVAL_SIMPLIFIED = 500; + + private static final int DEFAULT_WIDTH = 4; + + @Override + protected void installDefaults() { + super.installDefaults(); + UIManager.put("ProgressBar.repaintInterval", isSimplified() ? REPAINT_INTERVAL_SIMPLIFIED : REPAINT_INTERVAL_DEFAULT); + UIManager.put("ProgressBar.cycleTime", isSimplified() ? CYCLE_TIME_SIMPLIFIED : CYCLE_TIME_DEFAULT); + trackColor = UIManager.getColor("ProgressBar.trackColor"); + progressColor = UIManager.getColor("ProgressBar.progressColor"); + indeterminateStartColor = UIManager.getColor("ProgressBar.indeterminateStartColor"); + indeterminateEndColor = UIManager.getColor("ProgressBar.indeterminateEndColor"); + + failedColor = UIManager.getColor("ProgressBar.failedColor"); + failedEndColor = UIManager.getColor("ProgressBar.failedEndColor"); + passedColor = UIManager.getColor("ProgressBar.passedColor"); + passedEndColor = UIManager.getColor("ProgressBar.passedEndColor"); + } + + @Override + protected void paintIndeterminate(@NotNull final Graphics g, @NotNull final JComponent c) { + + Graphics2D g2 = (Graphics2D) g.create(); + try { + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + Rectangle r = new Rectangle(progressBar.getSize()); + if (c.isOpaque()) { + g2.setColor(c.getParent().getBackground()); + g2.fill(r); + } + + Insets i = progressBar.getInsets(); + DarkUIUtil.removeInsets(r, i); + int orientation = progressBar.getOrientation(); + + Color startColor, endColor; + if (hasFailed(progressBar)) { + startColor = failedColor; + endColor = failedEndColor; + } else if (hasPassed(progressBar)) { + startColor = passedColor; + endColor = passedEndColor; + } else { + startColor = getStartColor(); + endColor = getEndColor(); + } + + int pHeight = progressBar.getPreferredSize().height; + int pWidth = progressBar.getPreferredSize().width; + + int yOffset = r.y + (r.height - pHeight) / 2; + int xOffset = r.x + (r.width - pWidth) / 2; + + if (isSimplified()) { + Color[] ca = {startColor, endColor}; + int idx = 0; + int delta = 10; + if (orientation == SwingConstants.HORIZONTAL) { + for (float offset = r.x; offset - r.x < r.width; offset += delta) { + g2.setPaint(ca[(getAnimationIndex() + idx++) % 2]); + g2.fill(new Rectangle2D.Float(offset, yOffset, delta, pHeight)); + } + } else { + for (float offset = r.y; offset - r.y < r.height; offset += delta) { + g2.setPaint(ca[(getAnimationIndex() + idx++) % 2]); + g2.fill(new Rectangle2D.Float(xOffset, offset, delta, pWidth)); + } + } + } else { + Shape shape; + int step = 6; + if (orientation == SwingConstants.HORIZONTAL) { + shape = getShapedRect(r.x, yOffset, r.width, pHeight, pHeight); + yOffset = r.y + pHeight / 2; + g2.setPaint(new GradientPaint(r.x + getAnimationIndex() * step * 2, yOffset, startColor, + r.x + getFrameCount() * step + getAnimationIndex() * step * 2, yOffset, + endColor, true)); + } else { + shape = getShapedRect(xOffset, r.y, pWidth, r.height, pWidth); + xOffset = r.x + pWidth / 2; + g2.setPaint(new GradientPaint(xOffset, r.y + getAnimationIndex() * step * 2, startColor, + xOffset, r.y + getFrameCount() * step + getAnimationIndex() * step * 2, + endColor, true)); + } + g2.fill(shape); + } + + // Paint text + if (progressBar.isStringPainted()) { + if (progressBar.getOrientation() == SwingConstants.HORIZONTAL) { + paintString((Graphics2D) g, i.left, i.top, r.width, r.height, + boxRect.x, boxRect.width); + } else { + paintString((Graphics2D) g, i.left, i.top, r.width, r.height, + boxRect.y, boxRect.height); + } + } + } finally { + g2.dispose(); + } + } + + protected Color getStartColor() { + return indeterminateStartColor; + } + + protected Color getEndColor() { + return indeterminateEndColor; + } + + 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) { + String progressString = progressBar.getString(); + g.setFont(progressBar.getFont()); + Point renderLocation = getStringPlacement(g, progressString, x, y, w, h); + + var config = GraphicsUtil.setupAAPainting(g); + if (progressBar.getOrientation() == SwingConstants.HORIZONTAL) { + g.setColor(getSelectionBackground()); + g.drawString(progressString, renderLocation.x, renderLocation.y); + + g.setColor(getSelectionForeground()); + g.clipRect(fillStart, y, amountFull, h); + g.drawString(progressString, renderLocation.x, renderLocation.y); + + } else { // VERTICAL + g.setColor(getSelectionBackground()); + AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2); + g.setFont(progressBar.getFont().deriveFont(rotate)); + renderLocation = getStringPlacement(g, progressString, x, y, w, h); + g.drawString(progressString, renderLocation.x, renderLocation.y); + + g.setColor(getSelectionForeground()); + g.clipRect(x, fillStart, w, amountFull); + + g.drawString(progressString, renderLocation.x, renderLocation.y); + } + config.restore(); + } + + @Override + protected void paintDeterminate(@NotNull final Graphics g, final JComponent c) { + Graphics2D g2 = (Graphics2D) g.create(); + try { + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + Rectangle r = new Rectangle(progressBar.getSize()); + if (c.isOpaque() && c.getParent() != null) { + g2.setColor(c.getParent().getBackground()); + g2.fill(r); + } + + Insets i = progressBar.getInsets(); + DarkUIUtil.removeInsets(r, i); + int amountFull = getAmountFull(i, r.width, r.height); + + Shape fullShape, coloredShape; + int orientation = progressBar.getOrientation(); + if (orientation == SwingConstants.HORIZONTAL) { + int pHeight = progressBar.getPreferredSize().height; + int yOffset = r.y + (r.height - pHeight) / 2; + + fullShape = getShapedRect(r.x, yOffset, r.width, pHeight, pHeight); + coloredShape = getShapedRect(r.x, yOffset, amountFull, pHeight, pHeight); + } else { + int pWidth = progressBar.getPreferredSize().width; + int xOffset = r.x + (r.width - pWidth) / 2; + + fullShape = getShapedRect(xOffset, r.y, pWidth, r.height, pWidth); + coloredShape = getShapedRect(xOffset, r.y, pWidth, amountFull, pWidth); + } + g2.setColor(getRemainderColor()); + g2.fill(fullShape); + + if (hasFailed(progressBar)) { + g2.setColor(failedColor); + } else if (hasPassed(progressBar)) { + g2.setColor(passedColor); + } else { + g2.setColor(getFinishedColor()); + } + g2.fill(coloredShape); + + if (progressBar.isStringPainted()) { + var config = GraphicsUtil.setupAAPainting(g); + paintString(g, i.left, i.top, r.width, r.height, amountFull, i); + config.restore(); + } + } finally { + g2.dispose(); + } + } + + protected static boolean hasFailed(@NotNull final JComponent c) { + return Boolean.TRUE.equals(c.getClientProperty("JProgressBar.failed")); + } + + protected static boolean hasPassed(@NotNull final JComponent c) { + return Boolean.TRUE.equals(c.getClientProperty("JProgressBar.passed")); + } + + protected Color getRemainderColor() { + return trackColor; + } + + protected Color getFinishedColor() { + return progressColor; + } + + @Override + public Dimension getPreferredSize(final JComponent c) { + Dimension size = super.getPreferredSize(c); + if (!(c instanceof JProgressBar)) { + return size; + } + if (!((JProgressBar) c).isStringPainted()) { + if (((JProgressBar) c).getOrientation() == SwingConstants.HORIZONTAL) { + size.height = getStripeWidth(); + } else { + size.width = getStripeWidth(); + } + } + return size; + } + + private int getStripeWidth() { + Object ho = progressBar.getClientProperty("ProgressBar.stripeWidth"); + if (ho != null) { + try { + return Integer.parseInt(ho.toString()); + } catch (NumberFormatException nfe) { + return DEFAULT_WIDTH; + } + } else { + return DEFAULT_WIDTH; + } + } + + @Override + protected int getBoxLength(final int availableLength, final int otherDimension) { + return availableLength; + } + + @NotNull + @Contract("_, _, _, _, _ -> new") + private Shape getShapedRect(final float x, final float y, final float w, final float h, final float ar) { + return new RoundRectangle2D.Float(x, y, w, h, ar, ar); + } + + @Contract(pure = true) + private static boolean isSimplified() { + return UIManager.getBoolean("ProgressBar.isSimplified"); + } +} \ No newline at end of file diff --git a/src/main/java/com/weis/darklaf/ui/tooltip/DarkTooltipUI.java b/src/main/java/com/weis/darklaf/ui/tooltip/DarkTooltipUI.java index fbcea53a..defcf925 100644 --- a/src/main/java/com/weis/darklaf/ui/tooltip/DarkTooltipUI.java +++ b/src/main/java/com/weis/darklaf/ui/tooltip/DarkTooltipUI.java @@ -92,7 +92,7 @@ public class DarkTooltipUI extends BasicToolTipUI implements PropertyChangeListe } @Override - public void propertyChange(final PropertyChangeEvent evt) { + public void propertyChange(@NotNull final PropertyChangeEvent evt) { var key = evt.getPropertyName(); if (evt.getSource() instanceof JToolTip) { var tooltip = (JToolTip) evt.getSource(); diff --git a/src/main/java/com/weis/darklaf/util/DarkUIUtil.java b/src/main/java/com/weis/darklaf/util/DarkUIUtil.java index 1fcfdb28..fdde1226 100644 --- a/src/main/java/com/weis/darklaf/util/DarkUIUtil.java +++ b/src/main/java/com/weis/darklaf/util/DarkUIUtil.java @@ -156,6 +156,16 @@ public final class DarkUIUtil { } } + public static void removeInsets(final Rectangle rectangle, final Insets insets) { + if (insets != null) { + rectangle.x += insets.left; + rectangle.y += insets.top; + rectangle.width -= insets.left + insets.right; + rectangle.height -= insets.top + insets.bottom; + } + + } + public static boolean hasFocus(final Component c) { if (c instanceof Window) { return hasFocus(c); diff --git a/src/main/resources/com/weis/darklaf/properties/ui/progressBar.properties b/src/main/resources/com/weis/darklaf/properties/ui/progressBar.properties index 4c55bd28..1526fcb5 100644 --- a/src/main/resources/com/weis/darklaf/properties/ui/progressBar.properties +++ b/src/main/resources/com/weis/darklaf/properties/ui/progressBar.properties @@ -1,4 +1,17 @@ # suppress inspection "UnusedProperty" for whole file -ProgressBarUI = com.bulenkov.darcula.ui.DarculaProgressBarUI -ProgressBar.border = com.bulenkov.darcula.ui.DarculaProgressBarBorder -ProgressBar.foreground = 808080 \ No newline at end of file +ProgressBarUI = com.weis.darklaf.ui.progressbar.DarkProgressBarUI +ProgressBar.border = com.weis.darklaf.ui.progressbar.DarkProgressBarBorder +ProgressBar.foreground = %textForeground + +ProgressBar.trackColor = %controlBackground +ProgressBar.progressColor = %controlFill +ProgressBar.indeterminateStartColor = %controlFadeStart +ProgressBar.indeterminateEndColor = %controlFadeEnd + +ProgressBar.failedColor = %controlErrorFadeStart +ProgressBar.failedEndColor = %controlErrorFadeEnd +ProgressBar.passedColor = %controlPassedFadeStart +ProgressBar.passedEndColor = %controlPassedFadeEnd + +ProgressBar.isSimplified = false +ProgressBar.stripeWidth = 4 \ No newline at end of file diff --git a/src/main/resources/com/weis/darklaf/theme/darcula/darcula_defaults.properties b/src/main/resources/com/weis/darklaf/theme/darcula/darcula_defaults.properties index 1db3830e..b516620c 100644 --- a/src/main/resources/com/weis/darklaf/theme/darcula/darcula_defaults.properties +++ b/src/main/resources/com/weis/darklaf/theme/darcula/darcula_defaults.properties @@ -52,14 +52,18 @@ widgetFillDefault = 365880 ####Controls#### controlBorder = 6b6b6b controlBorderDisabled = 545556 -controlFill = A7A7A7 +controlFill = A0A0A0 controlFillSecondary = 636869 controlFillDisabled = 606060 controlFillHighlight = 5394ec controlFillHighlightDisabled = 475b81 -controlBackground = 2b2b2b -controlFadeStart = 5f5f5f -controlFadeEnd = 878787 +controlBackground = 555555 +controlFadeStart = 696969 +controlFadeEnd = 838383 +controlErrorFadeStart = e74848 +controlErrorFadeEnd = f4a2a0 +controlPassedFadeStart = 008f50 +controlPassedFadeEnd = 5dc48f ####Text#### caret = bbbbbb diff --git a/src/test/java/UIDemo.java b/src/test/java/UIDemo.java index b98a5cb8..a528ae97 100644 --- a/src/test/java/UIDemo.java +++ b/src/test/java/UIDemo.java @@ -30,7 +30,7 @@ public final class UIDemo { JFrame frame = new JFrame("UIDemo"); Icon folderIcon = IconLoader.get().getUIAwareIcon("files/folder.svg", 19, 19); - var panel = new JPanel(new GridLayout(2, 5)); + var panel = new JPanel(new GridLayout(3, 4)); var content = new JPanel(new BorderLayout()); content.add(panel, BorderLayout.CENTER); var statusBar = new JXStatusBar(); @@ -162,7 +162,30 @@ public final class UIDemo { }}); }}); panel.add(taskpanecontainer); - panel.add(new JPanel()); + panel.add(new JPanel() {{ + add(new JProgressBar() {{ + setValue(50); + }}); + add(new JProgressBar() {{ + setValue(50); + putClientProperty("JProgressBar.failed", true); + }}); + add(new JProgressBar() {{ + setValue(50); + putClientProperty("JProgressBar.passed", true); + }}); + add(new JProgressBar() {{ + setIndeterminate(true); + }}); + add(new JProgressBar() {{ + setIndeterminate(true); + putClientProperty("JProgressBar.failed", true); + }}); + add(new JProgressBar() {{ + setIndeterminate(true); + putClientProperty("JProgressBar.passed", true); + }}); + }}); panel.add(new JPanel() {{ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(new JSlider()); @@ -375,9 +398,8 @@ public final class UIDemo { menuBar.add(menu); frame.setJMenuBar(menuBar); - frame.setMinimumSize(new Dimension(100, 100)); frame.getRootPane().setDefaultButton(defaultButton); - frame.pack(); + frame.setSize(1200, 800); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);