From c3beb1631bea0e2c444d5f2af7a45576e6e47927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Levy=2EXie-=E8=A7=A3=E5=AE=89=E6=A3=AE?= Date: Thu, 26 Dec 2024 19:54:56 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-145112=20=E4=BB=A3=E7=A0=81=E8=B4=A8?= =?UTF-8?q?=E9=87=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fine/component/popup/ComponentLayer.java | 68 ++++++---- .../fine/component/popup/GlassPaneChild.java | 12 ++ .../com/fine/component/popup/GlassPopup.java | 30 +++-- .../com/fine/component/popup/ImageChild.java | 8 +- .../fine/component/popup/WindowSnapshots.java | 36 ++--- .../com/fine/theme/light/ui/ShadowBorder.java | 5 +- .../com/fine/theme/light/ui/ToastPanelUI.java | 6 +- .../com/fine/theme/utils/ShadowRenderer.java | 123 +++++++++++------- 8 files changed, 180 insertions(+), 108 deletions(-) diff --git a/designer-base/src/main/java/com/fine/component/popup/ComponentLayer.java b/designer-base/src/main/java/com/fine/component/popup/ComponentLayer.java index a69ca0fe0a..ccd2b13be6 100755 --- a/designer-base/src/main/java/com/fine/component/popup/ComponentLayer.java +++ b/designer-base/src/main/java/com/fine/component/popup/ComponentLayer.java @@ -128,7 +128,9 @@ public class ComponentLayer extends JPanel { private void showComponent(GlassPaneChild component) { showSnapshot = true; this.nextComponent = component; - image = FineUIUtils.createImage(this.component); + if (!component.isTransparent()) { + image = FineUIUtils.createImage(this.component); + } if (component.getRoundBorder() > 0) { setOpaque(false); component.setOpaque(false); @@ -149,7 +151,9 @@ public class ComponentLayer extends JPanel { } simpleSnapshot = true; doLayout(); - image = FineUIUtils.createImage(component, component.getRoundBorder()); + if (!component.isTransparent()) { + image = FineUIUtils.createImage(component, component.getRoundBorder()); + } component.setVisible(false); } @@ -167,13 +171,15 @@ public class ComponentLayer extends JPanel { @Override protected void paintComponent(Graphics g) { - if (!isOpaque() && component.getRoundBorder() > 0) { - Graphics2D g2 = (Graphics2D) g.create(); - FlatUIUtils.setRenderingHints(g2); - g2.setColor(getBackground()); - int arc = UIScale.scale(component.getRoundBorder()); - FlatUIUtils.paintComponentBackground(g2, 0, 0, getWidth(), getHeight(), 0, arc); - g2.dispose(); + if (!component.isTransparent()) { + if (!isOpaque() && component.getRoundBorder() > 0) { + Graphics2D g2 = (Graphics2D) g.create(); + FlatUIUtils.setRenderingHints(g2); + g2.setColor(getBackground()); + int arc = UIScale.scale(component.getRoundBorder()); + FlatUIUtils.paintComponentBackground(g2, 0, 0, getWidth(), getHeight(), 0, arc); + g2.dispose(); + } } super.paintComponent(g); } @@ -193,26 +199,10 @@ public class ComponentLayer extends JPanel { g2.setColor(getBackground()); FlatUIUtils.paintComponentBackground(g2, 0, 0, width, height, 0, arc); if (image != null) { - int w = image.getWidth(null); - double x; - if (push) { - x = -w * animate; - } else { - x = w * animate; - } - g2.setComposite(AlphaComposite.SrcAtop.derive(1f - animate)); - g2.drawImage(image, (int) x, 0, null); + paintImage(g2); } if (nextImage != null) { - int w = nextImage.getWidth(null); - double x; - if (push) { - x = getWidth() - (w * animate); - } else { - x = -getWidth() + (w * animate); - } - g2.setComposite(AlphaComposite.SrcAtop.derive(animate)); - g2.drawImage(nextImage, (int) x, 0, null); + paintNextImage(g2); } g2.dispose(); g.drawImage(bufferedImage, 0, 0, null); @@ -222,6 +212,30 @@ public class ComponentLayer extends JPanel { } } + private void paintNextImage(Graphics2D g2) { + int w = nextImage.getWidth(null); + double x; + if (push) { + x = getWidth() - (w * animate); + } else { + x = -getWidth() + (w * animate); + } + g2.setComposite(AlphaComposite.SrcAtop.derive(animate)); + g2.drawImage(nextImage, (int) x, 0, null); + } + + private void paintImage(Graphics2D g2) { + int w = image.getWidth(null); + double x; + if (push) { + x = -w * animate; + } else { + x = w * animate; + } + g2.setComposite(AlphaComposite.SrcAtop.derive(1f - animate)); + g2.drawImage(image, (int) x, 0, null); + } + public GlassPaneChild getComponent() { return component; } diff --git a/designer-base/src/main/java/com/fine/component/popup/GlassPaneChild.java b/designer-base/src/main/java/com/fine/component/popup/GlassPaneChild.java index 4d248b5cf3..fc09817c31 100755 --- a/designer-base/src/main/java/com/fine/component/popup/GlassPaneChild.java +++ b/designer-base/src/main/java/com/fine/component/popup/GlassPaneChild.java @@ -13,10 +13,21 @@ import javax.swing.JPanel; */ public class GlassPaneChild extends JPanel { + protected boolean transparent; + public int getRoundBorder() { return FlatUIUtils.getUIInt("Component.arc", 6); } + /** + * 组件是否透明 + * + * @return 组件透明 + */ + protected boolean isTransparent() { + return transparent; + } + /** * 放入组件时的回调方法 */ @@ -35,6 +46,7 @@ public class GlassPaneChild extends JPanel { * 显示弹窗组件时的回调方法 */ public void popupShow() { + } /** diff --git a/designer-base/src/main/java/com/fine/component/popup/GlassPopup.java b/designer-base/src/main/java/com/fine/component/popup/GlassPopup.java index 1159f35475..f681f76dab 100755 --- a/designer-base/src/main/java/com/fine/component/popup/GlassPopup.java +++ b/designer-base/src/main/java/com/fine/component/popup/GlassPopup.java @@ -59,26 +59,34 @@ public class GlassPopup extends JComponent { @Override public void begin() { - componentLayer.showSnapshot(); - parent.windowSnapshots.createSnapshot(); - parent.contentPane.setVisible(false); + prepareAnimation(); } @Override public void end() { - componentLayer.hideSnapshot(); - if (show) { - componentLayer.getComponent().popupShow(); - } else { - parent.removePopup(GlassPopup.this); - } - parent.contentPane.setVisible(true); - parent.windowSnapshots.removeSnapshot(); + finishAnimation(); } }); animator.setInterpolator(CubicBezierEasing.EASE); } + private void prepareAnimation() { + componentLayer.showSnapshot(); + parent.windowSnapshots.createSnapshot(); + parent.contentPane.setVisible(false); + } + + private void finishAnimation() { + componentLayer.hideSnapshot(); + if (show) { + componentLayer.getComponent().popupShow(); + } else { + parent.removePopup(GlassPopup.this); + } + parent.contentPane.setVisible(true); + parent.windowSnapshots.removeSnapshot(); + } + public void setShowPopup(boolean show) { if (this.show != show) { // 前置动画未结束时,先关闭前置动画 diff --git a/designer-base/src/main/java/com/fine/component/popup/ImageChild.java b/designer-base/src/main/java/com/fine/component/popup/ImageChild.java index 5fd01ac63d..adf14061f1 100644 --- a/designer-base/src/main/java/com/fine/component/popup/ImageChild.java +++ b/designer-base/src/main/java/com/fine/component/popup/ImageChild.java @@ -11,7 +11,7 @@ import java.util.Objects; * 图片遮罩层,支撑静态图片及动态GIF * * @author Levy.Xie - * @since 11.0 + * @since 12.0 * Created on 2024/12/20 */ public class ImageChild extends GlassPaneChild { @@ -23,6 +23,12 @@ public class ImageChild extends GlassPaneChild { } public ImageChild(String imgPath) { + this(imgPath, true); + } + + public ImageChild(String imgPath, boolean transparent) { + this.transparent = transparent; + setLayout(new BorderLayout()); setBorder(new ScaledEmptyBorder(8, 8, 8, 8)); ImageIcon icon = new ImageIcon(Objects.requireNonNull(getClass().getClassLoader().getResource(imgPath))); diff --git a/designer-base/src/main/java/com/fine/component/popup/WindowSnapshots.java b/designer-base/src/main/java/com/fine/component/popup/WindowSnapshots.java index 6ecfe471dd..409acc15ea 100755 --- a/designer-base/src/main/java/com/fine/component/popup/WindowSnapshots.java +++ b/designer-base/src/main/java/com/fine/component/popup/WindowSnapshots.java @@ -1,5 +1,7 @@ package com.fine.component.popup; +import org.jetbrains.annotations.NotNull; + import javax.swing.JComponent; import javax.swing.JLayeredPane; import javax.swing.JRootPane; @@ -39,21 +41,7 @@ public class WindowSnapshots { JLayeredPane layeredPane = getLayeredPane(); if (layeredPane != null) { layeredPane.paint(snapshot.getGraphics()); - snapshotLayer = new JComponent() { - @Override - public void paint(Graphics g) { - if (snapshot.contentsLost()) { - return; - } - g.drawImage(snapshot, 0, 0, null); - } - - @Override - public void removeNotify() { - super.removeNotify(); - snapshot.flush(); - } - }; + snapshotLayer = createSnapLayer(snapshot); snapshotLayer.setSize(layeredPane.getSize()); layeredPane.add(snapshotLayer, Integer.valueOf(JLayeredPane.DRAG_LAYER + 1)); } @@ -61,6 +49,24 @@ public class WindowSnapshots { } } + private static @NotNull JComponent createSnapLayer(VolatileImage snapshot) { + return new JComponent() { + @Override + public void paint(Graphics g) { + if (snapshot.contentsLost()) { + return; + } + g.drawImage(snapshot, 0, 0, null); + } + + @Override + public void removeNotify() { + super.removeNotify(); + snapshot.flush(); + } + }; + } + /** * 移除窗口快照覆盖层 */ diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/ShadowBorder.java b/designer-base/src/main/java/com/fine/theme/light/ui/ShadowBorder.java index 16cbad12a0..637879f018 100755 --- a/designer-base/src/main/java/com/fine/theme/light/ui/ShadowBorder.java +++ b/designer-base/src/main/java/com/fine/theme/light/ui/ShadowBorder.java @@ -5,6 +5,7 @@ import com.formdev.flatlaf.FlatPropertiesLaf; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.UIScale; +import com.fr.stable.AssistUtils; import javax.swing.JComponent; import javax.swing.border.EmptyBorder; @@ -73,7 +74,9 @@ public class ShadowBorder extends EmptyBorder { public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { JComponent com = (JComponent) c; int arc = FlatPropertiesLaf.getStyleableValue(com, "arc"); - if (shadowImage == null || !shadowColor.equals(lastShadowColor) || width != lastWidth || height != lastHeight || shadowSize != lastShadowSize || shadowOpacity != lastShadowOpacity || arc != lastArc) { + if (shadowImage == null || !shadowColor.equals(lastShadowColor) + || width != lastWidth || height != lastHeight || shadowSize != lastShadowSize + || !AssistUtils.equals(shadowOpacity, lastShadowOpacity) || arc != lastArc) { shadowImage = createShadowImage(width, height, arc); lastShadowColor = shadowColor; lastWidth = width; diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/ToastPanelUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/ToastPanelUI.java index dd079693a1..ad0dcdc8bf 100755 --- a/designer-base/src/main/java/com/fine/theme/light/ui/ToastPanelUI.java +++ b/designer-base/src/main/java/com/fine/theme/light/ui/ToastPanelUI.java @@ -136,24 +136,22 @@ public class ToastPanelUI extends BasicPanelUI implements StyleableUI, PropertyC @Override public void propertyChange(PropertyChangeEvent e) { + JPanel c = (JPanel) e.getSource(); switch (e.getPropertyName()) { default: case TOAST_ICON: { - JPanel c = (JPanel) e.getSource(); uninstallIconComponent(c); installIconComponent(c); refreshUI(c); break; } case TOAST_COMPONENT: { - JPanel c = (JPanel) e.getSource(); uninstallComponent(c); installComponent(c); refreshUI(c); break; } case TOAST_SHOW_CLOSE_BUTTON: { - JPanel c = (JPanel) e.getSource(); uninstallCloseButton(c); installCloseButton(c); refreshUI(c); @@ -161,7 +159,6 @@ public class ToastPanelUI extends BasicPanelUI implements StyleableUI, PropertyC } case STYLE: case STYLE_CLASS: { - JPanel c = (JPanel) e.getSource(); installStyle(c); refreshUI(c); break; @@ -174,7 +171,6 @@ public class ToastPanelUI extends BasicPanelUI implements StyleableUI, PropertyC c.repaint(); } - private void installIconComponent(JComponent c) { iconComponent = clientProperty(c, TOAST_ICON, null, JComponent.class); if (iconComponent != null) { diff --git a/designer-base/src/main/java/com/fine/theme/utils/ShadowRenderer.java b/designer-base/src/main/java/com/fine/theme/utils/ShadowRenderer.java index 801c4ef8b2..58e3b90046 100755 --- a/designer-base/src/main/java/com/fine/theme/utils/ShadowRenderer.java +++ b/designer-base/src/main/java/com/fine/theme/utils/ShadowRenderer.java @@ -1,5 +1,7 @@ package com.fine.theme.utils; +import org.jetbrains.annotations.NotNull; + import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; @@ -77,86 +79,111 @@ public class ShadowRenderer { int yStop = dstHeight - right; int shadowRgb = color.getRGB() & 0x00FFFFFF; int[] aHistory = new int[shadowSize]; - int historyIdx; - int aSum; BufferedImage dst = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB); int[] dstBuffer = new int[dstWidth * dstHeight]; int[] srcBuffer = new int[srcWidth * srcHeight]; getPixels(image, 0, 0, srcWidth, srcHeight, srcBuffer); int lastPixelOffset = right * dstWidth; - float hSumDivider = 1.0f / shadowSize; - float vSumDivider = opacity / shadowSize; - int[] hSumLookup = new int[256 * shadowSize]; - for (int i = 0; i < hSumLookup.length; i++) { - hSumLookup[i] = (int) (i * hSumDivider); - } - int[] vSumLookup = new int[256 * shadowSize]; - for (int i = 0; i < vSumLookup.length; i++) { - vSumLookup[i] = (int) (i * vSumDivider); + + int[] hSumLookup = initSumLookupArray(1.0f, shadowSize); + int[] vSumLookup = initSumLookupArray(opacity, shadowSize); + + applyHorizontalShadowBlur(left, dstWidth, srcHeight, shadowSize, aHistory, srcWidth, hSumLookup, dstBuffer, srcBuffer); + + applyVerticalShadowBlur(dstWidth, left, aHistory, right, dstBuffer, yStop, vSumLookup, shadowRgb, + lastPixelOffset, shadowSize, dstHeight); + + setPixels(dst, 0, 0, dstWidth, dstHeight, dstBuffer); + return dst; + } + + private static int @NotNull [] initSumLookupArray(float x, int shadowSize) { + float sumDivider = x / shadowSize; + int[] sumLookup = new int[256 * shadowSize]; + for (int i = 0; i < sumLookup.length; i++) { + sumLookup[i] = (int) (i * sumDivider); } - int srcOffset; - for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) { - for (historyIdx = 0; historyIdx < shadowSize; ) { - aHistory[historyIdx++] = 0; - } - aSum = 0; - historyIdx = 0; - srcOffset = srcY * srcWidth; - for (int srcX = 0; srcX < srcWidth; srcX++) { - int a = hSumLookup[aSum]; - dstBuffer[dstOffset++] = a << 24; + return sumLookup; + } + + private static void applyVerticalShadowBlur(int dstWidth, int left, int[] aHistory, int right, int[] dstBuffer, + int yStop, int[] vSumLookup, int shadowRgb, int lastPixelOffset, + int shadowSize, int dstHeight) { + for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) { + int aSum = initializeAlphaSum(dstWidth, left, aHistory, right, dstBuffer, bufferOffset, 0); + bufferOffset = x; + int historyIdx = 0; + for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) { + int a = vSumLookup[aSum]; + dstBuffer[bufferOffset] = a << 24 | shadowRgb; aSum -= aHistory[historyIdx]; - a = srcBuffer[srcOffset + srcX] >>> 24; + a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24; aHistory[historyIdx] = a; aSum += a; if (++historyIdx >= shadowSize) { historyIdx -= shadowSize; } } - for (int i = 0; i < shadowSize; i++) { - int a = hSumLookup[aSum]; - dstBuffer[dstOffset++] = a << 24; + for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) { + int a = vSumLookup[aSum]; + dstBuffer[bufferOffset] = a << 24 | shadowRgb; aSum -= aHistory[historyIdx]; if (++historyIdx >= shadowSize) { historyIdx -= shadowSize; } } } + } + + private static int initializeAlphaSum(int dstWidth, int left, int[] aHistory, int right, int[] dstBuffer, int bufferOffset, int aSum) { + int historyIdx; + for (historyIdx = 0; historyIdx < left; ) { + aHistory[historyIdx++] = 0; + } + for (int y = 0; y < right; y++, bufferOffset += dstWidth) { + int a = dstBuffer[bufferOffset] >>> 24; + aHistory[historyIdx++] = a; + aSum += a; + } + return aSum; + } - for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) { - aSum = 0; - for (historyIdx = 0; historyIdx < left; ) { + private static void applyHorizontalShadowBlur(int left, int dstWidth, int srcHeight, int shadowSize, + int[] aHistory, int srcWidth, int[] hSumLookup, int[] dstBuffer, int[] srcBuffer) { + int historyIdx; + for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) { + for (historyIdx = 0; historyIdx < shadowSize; ) { aHistory[historyIdx++] = 0; } - for (int y = 0; y < right; y++, bufferOffset += dstWidth) { - int a = dstBuffer[bufferOffset] >>> 24; - aHistory[historyIdx++] = a; - aSum += a; - } - bufferOffset = x; + int aSum = 0; historyIdx = 0; - for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) { - int a = vSumLookup[aSum]; - dstBuffer[bufferOffset] = a << 24 | shadowRgb; + int srcOffset = srcY * srcWidth; + for (int srcX = 0; srcX < srcWidth; srcX++) { + int a = hSumLookup[aSum]; + dstBuffer[dstOffset++] = a << 24; aSum -= aHistory[historyIdx]; - a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24; + a = srcBuffer[srcOffset + srcX] >>> 24; aHistory[historyIdx] = a; aSum += a; if (++historyIdx >= shadowSize) { historyIdx -= shadowSize; } } - for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) { - int a = vSumLookup[aSum]; - dstBuffer[bufferOffset] = a << 24 | shadowRgb; - aSum -= aHistory[historyIdx]; - if (++historyIdx >= shadowSize) { - historyIdx -= shadowSize; - } + dstOffset = updateDstBufferOffset(shadowSize, aHistory, hSumLookup, dstBuffer, aSum, dstOffset, historyIdx); + } + } + + private static int updateDstBufferOffset(int shadowSize, int[] aHistory, int[] hSumLookup, int[] dstBuffer, + int aSum, int dstOffset, int historyIdx) { + for (int i = 0; i < shadowSize; i++) { + int a = hSumLookup[aSum]; + dstBuffer[dstOffset++] = a << 24; + aSum -= aHistory[historyIdx]; + if (++historyIdx >= shadowSize) { + historyIdx -= shadowSize; } } - setPixels(dst, 0, 0, dstWidth, dstHeight, dstBuffer); - return dst; + return dstOffset; } private int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) {