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
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); |
|
} |
|
} |
|
} |