帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

403 lines
14 KiB

package com.fr.design.designer.creator;
import com.fr.base.BaseFormula;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.design.border.UIRoundedBorder;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Label;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.PaddingMargin;
import com.fr.form.ui.Widget;
import com.fr.form.ui.WidgetTitle;
import com.fr.form.ui.WidgetValue;
import com.fr.form.ui.container.WTitleLayout;
import com.fr.general.Background;
import com.fr.general.ComparatorUtils;
import com.fr.general.act.BorderPacker;
import com.fr.general.act.TitlePacker;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.basic.BasicPanelUI;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
/**
* Created with IntelliJ IDEA.
* User: zx
* Date: 14-9-22
* Time: 上午10:40
*/
public class XBorderStyleWidgetCreator extends XWidgetCreator{
protected static final Dimension BORDER_PREFERRED_SIZE = new Dimension(250, 150);
protected Background background4Painting; // 设计器预览界面中绘制组件背景图
protected double backgroundOpacity4Painting; // 设计器预览界面中绘制组件背景图
protected Background borderImage4Painting; // 设计器预览界面中绘制边框图片
protected double borderImageOpacity4Painting;
public XBorderStyleWidgetCreator(Widget widget, Dimension initSize) {
super(widget, initSize);
setUI(new NoBackgroundPaneUI());
setOpaque(false);
setBackupBound(null);
ExtendSharableAttrMark sharableAttrMark = this.toData().getWidgetAttrMark(ExtendSharableAttrMark.XML_TAG);
if (sharableAttrMark != null) {
this.setShareId(sharableAttrMark.getShareId());
}
}
@Override
public void setUI(PanelUI ui) {
if (ui instanceof NoBackgroundPaneUI) {
super.setUI(ui);
}
}
public Background getBackground4Painting() {
return this.background4Painting;
}
public double getBackgroundOpacity4Painting() {
return backgroundOpacity4Painting;
}
public void setBackground4Painting(Background background, double opacity) {
this.background4Painting = background;
this.backgroundOpacity4Painting = opacity;
}
public Background getBorderImage4Painting() {
return borderImage4Painting;
}
public double getBorderImageOpacity4Painting() {
return borderImageOpacity4Painting;
}
public void setBorderImage4Painting(Background borderImage, double opacity) {
this.borderImage4Painting = borderImage;
this.borderImageOpacity4Painting = opacity;
}
/**
* 返回容器对应的widget
* @return 同上
*/
@Override
public AbstractBorderStyleWidget toData() {
return (AbstractBorderStyleWidget) data;
}
@Override
protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight) {
super.addToWrapper(parentPanel, width, minHeight);
// REPORT-53175: 新创建的图表组件默认显示标题 since 10.0.18
// 将当前对象添加到父容器后,初始化默认样式的效果
refreshStylePreviewEffect();
}
public void refreshStylePreviewEffect() {
BorderPacker style = toData().getBorderStyle();
refreshBorderAndBackgroundStylePreviewEffect();
if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) {
initTitleStyle(style);
} else {
clearTitleWidget();
}
// 编辑右侧栏组件样式面板后,重新调整组件/标题/边框的显示效果
reshuffleBorderAndBackgroundPaintingEffectIfTitleExists();
}
public void refreshBorderAndBackgroundStylePreviewEffect() {
BorderPacker style = toData().getBorderStyle();
LineBorder DEFAULT_LINE_BORDER = (LineBorder) DEFALUTBORDER;
// 边框默认值设为NONE,不然像scalelayout这种只用默认边框的会不显示边框
Border border = DEFAULT_LINE_BORDER;
if (style != null) {
int radius = style.getBorderRadius(); // 不管有无边框线, 圆角裁剪总是生效
if (style.getBorder() != Constants.LINE_NONE) {
// 设置了边框线
border = new UIRoundedBorder(style.getBorder(), style.getColor(), radius);
} else {
// 为设置边框线
border = new UIRoundedBorder(DEFAULT_LINE_BORDER.getLineColor(), DEFAULT_LINE_BORDER.getThickness(), radius);
}
}
this.setBorder(border);
if (style != null) {
this.setBorderImage4Painting(style.getBorderImage(), style.getBorderImageOpacity());
this.setBackground4Painting(style.getBackground(), style.getAlpha());
} else {
this.setBorderImage4Painting(null, 0.0);
this.setBackground4Painting(null, 0.0);
}
}
private void clearTitleWidget() {
if (acceptType(XWFitLayout.class)) {
return;
}
XWTitleLayout parent = (XWTitleLayout) this.getParent();
if (parent.getComponentCount() > 1) {
parent.remove(parent.getTitleCreator());
}
}
/**
* 设置样式为标题样式时,对应组件加上标题
* @param style 样式
*/
protected void initTitleStyle(BorderPacker style){
if (style.getTitle() == null || style.getTitle().getTextObject() == null) {
return;
}
XWTitleLayout parent = (XWTitleLayout) this.getParent();
if (parent.getComponentCount() > 1) {
XLabel title = (XLabel) parent.getTitleCreator();
Label widget = title.toData();
updateTitleWidgetStyle(widget, style);
title.initXCreatorProperties();
return;
}
// 初始化标题控件
XLabel title = new XLabel(new Label(), new Dimension());
Label label = title.toData();
updateTitleWidgetStyle(label, style);
parent.add(title, WTitleLayout.TITLE);
// 初始化标题边框
title.initXCreatorProperties();
WTitleLayout layout = parent.toData();
layout.updateChildBounds(layout.getBodyBoundsWidget().getBounds());
}
/**
* 更新标题控件所有的样式
*/
private void updateTitleWidgetStyle(Label title, BorderPacker style) {
//标题的边框样式目前是取对应的控件的边框样式
title.setBorder(style.getBorder());
title.setColor(style.getColor());
// title.setCorner(style.isCorner());
TitlePacker wTitle = style.getTitle();
//设置成随机不重复的, 不然都用一个名字的话, 联动只能联动一个
title.setWidgetName(WidgetTitle.TITLE_NAME_INDEX + this.toData().getWidgetName());
title.setWidgetValue(getTitleValue(wTitle));
title.setFont(wTitle.getFrFont());
title.setTextalign(wTitle.getPosition());
title.setBackground(wTitle.getBackground());
title.setBackgroundOpacity(wTitle.getBackgroundOpacity());
title.setInsetImage(wTitle.getInsetImage());
title.setInsetImagePadding(wTitle.getInsetImagePadding());
title.setInsetRelativeTextLeft(wTitle.isInsetRelativeTextLeft());
title.setInsetRelativeTextRight(wTitle.isInsetRelativeTextRight());
}
private WidgetValue getTitleValue(TitlePacker wTitle){
String content = String.valueOf(wTitle.getTextObject());
Object value = content.startsWith("=") ? BaseFormula.createFormulaBuilder().build(content) : content;
return new WidgetValue(value);
}
// 如果存在标题栏,则需要重新弄调整边框和背景的显示效果,使得边框和背景的视觉效果出现在包含组件和标题的整体区域上,
// 而不是组件和标题各自出现独立的边框和背景,同时如存在标题栏,则标题栏下方还应有底部边框,作为标题和内容的分界线
protected void reshuffleBorderAndBackgroundPaintingEffectIfTitleExists() {
Container parent = this.getParent();
if (parent instanceof XWTitleLayout) {
XWTitleLayout titleParent = (XWTitleLayout) parent;
if (parent.getComponentCount() > 1) {
XCreator titleCreator = titleParent.getTitleCreator();
XCreator bodyXCreator = titleParent.getBodyCreator();
reshuffleBorderPaintingEffectIfTitleExists(titleParent, titleCreator, bodyXCreator);
reshuffleBackgroundPaintingEffectIfTitleExists(titleParent, titleCreator, bodyXCreator);
} else {
titleParent.setBorder(null);
titleParent.setBorderImage4Painting(null, 0.0);
titleParent.setBackground4Painting(null, 0.0);
}
}
}
private void reshuffleBorderPaintingEffectIfTitleExists(XWTitleLayout parentCreator, XCreator titleCreator, XCreator bodyCreator) {
Border border = bodyCreator.getBorder();
parentCreator.setBorder(border); // 容器绘制完整边框
bodyCreator.setBorder(BorderFactory.createEmptyBorder()); // body不绘制边框
titleCreator.setBorder(BorderFactory.createEmptyBorder()); // title绘制底部边框
if (border instanceof LineBorder) {
Color color = ((LineBorder) border).getLineColor();
int thickness = ((LineBorder) border).getThickness();
titleCreator.setBorder(new BottomLineBorder(color, thickness));
}
if (bodyCreator instanceof XBorderStyleWidgetCreator) {
XBorderStyleWidgetCreator styledBodyXCreator = (XBorderStyleWidgetCreator) bodyCreator;
Background borderImage= styledBodyXCreator.getBorderImage4Painting();
double opacity = styledBodyXCreator.getBorderImageOpacity4Painting();
styledBodyXCreator.setBorderImage4Painting(null, 0.0); // body不绘制图片边框
parentCreator.setBorderImage4Painting(borderImage, opacity); // 容器绘制完整图片边框
}
}
private void reshuffleBackgroundPaintingEffectIfTitleExists(XWTitleLayout parentCreator, XCreator titleCreator, XCreator bodyCreator) {
if (titleCreator instanceof XLabel) {
XLabel labelCreator = (XLabel) titleCreator;
Label titleLabel = labelCreator.toData();
Background background = titleLabel.getBackground();
double opacity = titleLabel.getBackgroundOpacity();
labelCreator.setEnabledBackgroundPainting(false); // 标题不绘制背景
parentCreator.setTitleBackground4Painting(background, opacity); // 容器绘制完整背景
}
if (bodyCreator instanceof XBorderStyleWidgetCreator) {
XBorderStyleWidgetCreator styledBodyXCreator = (XBorderStyleWidgetCreator) bodyCreator;
Background background = styledBodyXCreator.getBackground4Painting();
double opacity = styledBodyXCreator.getBackgroundOpacity4Painting();
styledBodyXCreator.setBackground4Painting(null, 0.0); // body不绘制背景
parentCreator.setBodyBackground4Painting(background, opacity); // 容器绘制完整背景
}
}
@Override
public void setBackground(Color bg) {
super.setBackground(bg);
}
// 根据当前组件边框裁剪内容,如果当前组件存在圆角,则应当按圆角裁剪内容
private void clipByRoundedBorder(Graphics2D g2d) {
Border currentBorder = getBorder();
if (currentBorder instanceof UIRoundedBorder) {
int thickness = ((UIRoundedBorder) currentBorder).getThickness();
int radius = ((UIRoundedBorder) currentBorder).getRoundedCorner();
int currentClipX = 0;
int currentClipY = 0;
int currentClipWidth = getWidth();
int currentClipHeight = getHeight();
int currentClipRadius = Math.max(radius - thickness, 0); // 应沿着边框外围进行裁剪
g2d.clip(new RoundRectangle2D.Double(currentClipX, currentClipY, currentClipWidth, currentClipHeight, currentClipRadius, currentClipRadius));
}
}
// 设计器预览界面中绘制组件背景效果
public void paintBackground(Graphics2D g2d) {
if (isOpaque()) {
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
Background background4Painting = getBackground4Painting();
if (background4Painting != null) {
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (float) backgroundOpacity4Painting));
Shape shape = new Rectangle2D.Double(0, 0, getWidth(), getHeight());
background4Painting.paint(g2d, shape);
g2d.setComposite(oldComposite);
}
}
public void paintBorderImage(Graphics2D g2d) {
Background borderImage4Painting = getBorderImage4Painting();
if (borderImage4Painting != null) {
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (float) borderImageOpacity4Painting));
borderImage4Painting.paint(g2d, new Rectangle2D.Double(0, 0, getWidth(), getHeight()));
g2d.setComposite(oldComposite);
}
}
public void paintForeground(Graphics2D g2d) {
super.paintComponent(g2d);
super.paintBorder(g2d);
}
@Override
public void paintComponent(Graphics g) {
this.clipByRoundedBorder((Graphics2D) g);
this.paintBackground((Graphics2D) g);
this.paintBorderImage((Graphics2D) g);
this.paintForeground((Graphics2D) g);
}
@Override
protected String getIconName() {
return StringUtils.EMPTY;
}
@Override
protected JComponent initEditor() {
return this;
}
/**
* 内边距
* @return 同上
*/
@Override
public Insets getInsets() {
PaddingMargin padding = toData().getMargin();
if (padding == null) {
return new Insets(0, 0, 0, 0);
}
return new Insets(padding.getTop(), padding.getLeft(), padding.getBottom(), padding.getRight());
}
/**
* data属性改变触发其他操作
*
*/
public void firePropertyChange() {
}
// 适用于标题栏的底部边框
public static class BottomLineBorder extends LineBorder {
private BottomLineBorder(Color color, int thickness) {
super(color, thickness);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D)g;
Color oldColor = g2d.getColor();
Stroke oldStroke = g2d.getStroke();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getLineColor());
g2d.setStroke(new BasicStroke(getThickness() * 2));
g2d.drawLine(0, height, width, height);
g2d.setStroke(oldStroke);
g2d.setColor(oldColor);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
}
}
public static class NoBackgroundPaneUI extends BasicPanelUI {
@Override
public void update(Graphics g, JComponent c) {
paint(g, c);
}
}
}