package com.fr.design.cell; import com.fr.base.CellBorderSourceFlag; import com.fr.base.CellBorderStyle; import com.fr.base.Style; import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.general.IOUtils; import com.fr.report.cell.TemplateCellElement; import javax.swing.JPanel; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.image.BufferedImage; /** * @author Starryi * @version 1.0 * Created by Starryi on 2021/9/3 */ public class CellRectangleStylePreviewPane extends JPanel { private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); private final float transparentBackgroundWidth; private final float transparentBackgroundHeight; private static final int ROW_COUNT = 2; private static final int COLUMN_COUNT = 2; private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT]; private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT]; private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT]; public CellRectangleStylePreviewPane(boolean supportInnerBorder) { transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); setLayout(new GridLayout(2, 2)); setOpaque(false); setBackground(null); for (int r = 0; r < ROW_COUNT; r++) { for (int c = 0; c < COLUMN_COUNT; c++) { CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false); TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r); int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE; if (supportInnerBorder) { flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER; if (r != 0) { flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER; } if (r != ROW_COUNT - 1) { flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER; } if (c != 0) { flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER; } if (c != COLUMN_COUNT - 1) { flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER; } } pane.setStyle(cellElement.getStyle()); add(pane); cellElementGrid[r][c] = cellElement; borderSourceFlags[r][c] = flags; cellStylePreviewPaneGrid[r][c] = pane; } } } public void setPlainText(String text) { cellStylePreviewPaneGrid[0][1].setPaintText(text); cellStylePreviewPaneGrid[1][1].setPaintText(text); repaint(); } public void setStyle(Style style, CellBorderStyle borderStyle) { for (int i = 0; i < ROW_COUNT; i++) { for (int j = 0; j < COLUMN_COUNT; j++) { CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j]; TemplateCellElement cellElement = cellElementGrid[i][j]; int flag = borderSourceFlags[i][j]; cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag)); pane.setStyle(cellElement.getStyle()); } } repaint(); } @Override public void setPreferredSize(Dimension preferredSize) { super.setPreferredSize(preferredSize); int hw = preferredSize.width / 2; int hh = preferredSize.height / 2; cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh)); cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh)); cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh)); cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh)); } @Override public Dimension getPreferredSize() { Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize(); Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize(); Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize(); Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize(); int width = Math.max(d00.width + d01.width, d10.width + d11.width); int height = Math.max(d00.height + d10.height, d01.height + d11.height); return new Dimension(width, height); } @Override public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.clearRect(0, 0, getWidth(), getHeight()); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); paintTransparentBackground((Graphics2D) g, cellElementGrid[0][0].getStyle()); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); super.paint(g); } @Override public Rectangle getBounds() { return super.getBounds(); } private void paintTransparentBackground(Graphics2D g2d, Style style) { float alpha = computeTransparentBackgroundAlpha(style); float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; float maxScale = Math.max(scaleWidth, scaleHeight); if (maxScale <= 1) { scaleWidth = scaleHeight = 1; } else { scaleHeight = scaleWidth = maxScale; } Composite oldComposite = g2d.getComposite(); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); g2d.setComposite(oldComposite); } private float computeTextColorBrightness(Style style) { Color fontColor = style.getFRFont().getForeground(); return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F; } private float computeTransparentBackgroundAlpha(Style style) { float textBrightness = computeTextColorBrightness(style); float alpha = 1.0F; if (textBrightness < 50) { alpha = 0.2F; } else if (textBrightness < 160){ alpha = 0.5F; } return alpha; } }