Browse Source

Pull request #7172: KERNEL-9636 && REPORT-63725 新自适应中设计器模块和主 jar 中的重复代码

Merge in DESIGN/design from ~KERRY/design_10.0:feature/x to feature/x

* commit 'a07d8a9f757ba54cd402f354a9c9c1e59f6cc682':
  KERNEL-9636 新自适应中设计器模块和主 jar 中的重复代码
feature/x
kerry 3 years ago
parent
commit
a3a656124e
  1. 1266
      designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java
  2. 2030
      designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java
  3. 20
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeAutoChangeLine.java
  4. 69
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeRotationDraw.java
  5. 835
      designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java
  6. 27
      designer-realize/src/main/java/com/fr/design/fit/AdaptiveCellElementPainter.java
  7. 21
      designer-realize/src/main/java/com/fr/design/fit/NewUIModeCellElementPainter.java
  8. 6
      designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java
  9. 12
      designer-realize/src/main/java/com/fr/grid/Grid.java
  10. 2
      designer-realize/src/main/java/com/fr/grid/GridUI.java

1266
designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java

File diff suppressed because it is too large Load Diff

2030
designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java

File diff suppressed because it is too large Load Diff

20
designer-form/src/main/java/com/fr/design/fit/common/NewUIModeAutoChangeLine.java

@ -0,0 +1,20 @@
package com.fr.design.fit.common;
import com.fr.base.DefaultAutoChangeLine;
import com.fr.base.Style;
import com.fr.stable.unit.UNIT;
import java.awt.Font;
import java.util.List;
public class NewUIModeAutoChangeLine extends DefaultAutoChangeLine {
@Override
public List<String> textAutoChangeLine(String text, Font font, Style style, UNIT unitWidth, int resolution) {
return autoChangeLine(text, font, style, unitWidth, resolution);
}
protected double calculateShowWidth(double paintWidth, Style style, int resolution) {
return paintWidth - style.getPaddingLeft() - style.getPaddingRight() - style.getBorderLeftWidth();
}
}

69
designer-form/src/main/java/com/fr/design/fit/common/NewUIModeRotationDraw.java

@ -0,0 +1,69 @@
package com.fr.design.fit.common;
import com.fr.base.BaseUtils;
import com.fr.base.DefaultRotationTextDrawProvider;
import com.fr.base.GraphHelper;
import com.fr.base.Style;
import com.fr.design.mainframe.PX;
import com.fr.stable.Constants;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.util.List;
public class NewUIModeRotationDraw extends DefaultRotationTextDrawProvider {
@Override
public void drawRotationText(Graphics2D g2d, String text, Style style, Font rfont, int width, int height, int horizontalAlignment, int resolution) {
FontMetrics cellFM = GraphHelper.getFontMetrics(rfont);
List lineTextList = BaseUtils.getLineTextList(text, style, rfont, height, width, resolution, new NewUIModeAutoChangeLine());
drawRotationText(g2d, lineTextList, style, cellFM, width, height, horizontalAlignment, resolution);
}
protected int calculateTextWidth(int width, Style style) {
return width - style.getPaddingRight();
}
protected double calculateTextX(Style style, int width, int textWidth, int horizontalAlignment, int resolution) {
double textX = padding2PixExcludeRight(style.getPaddingLeft(), resolution);
if (horizontalAlignment == Constants.CENTER) {
textX += (width - textWidth - textX) / 2f;
} else if (horizontalAlignment == Constants.RIGHT) {
textX = width - style.getPaddingRight() - textWidth;
}
return textX;
}
protected int toPXWithResolution(double pt, int resolution) {
return (int) PX.toPixWithResolution(pt, resolution);
}
protected double padding2PixExcludeRight(int padding, int resolution) {
return PX.toPixWithResolution(padding, resolution);
}
protected int calculateTextY(Style style, int height, int textHeight, int textAscent, List lineTextList, int resolution) {
// 计算Y的高度.
int textY = 0;
int textAllHeight = textHeight * lineTextList.size();
double spacingBefore = toPXWithResolution(style.getSpacingBefore(), resolution);
double spacingAfter = toPXWithResolution(style.getSpacingAfter(), resolution);
double lineSpacing = toPXWithResolution(style.getLineSpacing(), resolution);
textAllHeight += spacingBefore + spacingAfter + lineSpacing * lineTextList.size();
if (style.getVerticalAlignment() == Constants.TOP) {
} else if (style.getVerticalAlignment() == Constants.CENTER) {
if (height > textAllHeight) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符.
textY = (height - textAllHeight) / 2;
}
} else if (style.getVerticalAlignment() == Constants.BOTTOM) {
if (height > textAllHeight) {
textY = height - textAllHeight;
}
}
textY += textAscent;// 在绘画的时候,必须添加Ascent的高度.
textY += spacingBefore + lineSpacing;//james:加上"段前间距"+“行间距”
return textY;
}
}

835
designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java

@ -1,835 +0,0 @@
/*
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
*/
package com.fr.design.fit.common;
import com.fr.base.AutoChangeLineAndDrawManager;
import com.fr.base.BaseFormula;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.ImageProvider;
import com.fr.base.Painter;
import com.fr.base.Style;
import com.fr.base.Utils;
import com.fr.base.background.ColorBackground;
import com.fr.base.chart.BaseChartCollection;
import com.fr.base.chart.result.WebChartIDInfo;
import com.fr.code.BarcodeImpl;
import com.fr.code.bar.BarcodeException;
import com.fr.code.bar.core.BarCodeUtils;
import com.fr.code.bar.core.BarcodeAttr;
import com.fr.data.DataUtils;
import com.fr.data.PresentationType;
import com.fr.data.condition.ListCondition;
import com.fr.file.ResultChangeWhenExport;
import com.fr.form.ui.Widget;
import com.fr.general.Background;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
import com.fr.general.ImageWithSuffix;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.ExtraClassManager;
import com.fr.report.cell.CellElement;
import com.fr.report.cell.FloatElement;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.cell.cellattr.CellExpandAttr;
import com.fr.report.cell.cellattr.CellGUIAttr;
import com.fr.report.cell.cellattr.core.CellUtils;
import com.fr.report.cell.cellattr.core.ResultSubReport;
import com.fr.report.cell.cellattr.core.group.DSColumn;
import com.fr.report.core.Html2ImageUtils;
import com.fr.report.core.ReportUtils;
import com.fr.script.Calculator;
import com.fr.stable.Constants;
import com.fr.stable.CoreConstants;
import com.fr.stable.StringUtils;
import com.fr.stable.bridge.ObjectHolder;
import com.fr.stable.fun.AutoChangeLineAndDrawProcess;
import com.fr.stable.fun.FontProcessor;
import com.fr.stable.html.Tag;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.PT;
import com.fr.stable.unit.UNIT;
import com.fr.stable.web.Repository;
import javax.swing.ImageIcon;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.font.TextAttribute;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
/**
* The util for paint.
*/
public class PaintUtils {
// Add by Denny
public static final int CELL_MARK_SIZE = 6;
public static final Color CELL_HIGHT_LIGHT_MARK_COLOR = new Color(255, 0, 55);
public static final Color CELL_PRESENT_MARK_COLOR = new Color(0, 255, 200);
public static final Color CELL_PAGINATION_MARK_COLOR = new Color(55, 255, 0);
public static final Color CELL_RESULT_MARK_COLOR = new Color(200, 0, 255);
public static final Color CELL_CONDITION_FILTER_MARK_COLOR = new Color(255, 200, 0);
public static final Color CELL_PARAMETER_FILTER_MARK_CONLR = new Color(0, 55, 255);
public static final Color CELL_DIRECTION_MARK_COLOR = Color.gray;
private static final int UNIT_SIZE = 4;
//原值是15,矩形线条会缺失,加1px绘制没问题。这地方有水印,但是貌似不是水印影响,未找到线条被挡住的原因
private static final int WIDGET_WIDTH = 16;
private static final int WIDGET_HEIGHT = 16;
// Suppresses default constructor, ensuring non-instantiability.
private PaintUtils() {
}
// font attributes map cache
private static Hashtable fontAttributeMapCache = new Hashtable();
/*
* 用于在Grid里面画CellElement的Content + Background
*
* 不画Border,是因为在Grid里面先画所有单元格的Content + Background,再画所有单元格的Border(peter认为这可以提高速度)
*/
public static void paintGridCellContent(Graphics2D g2d, TemplateCellElement cell, int width, int height, int resolution) {
int cell_mark_size = CELL_MARK_SIZE;
// denny_Grid
// 左上角: 条件高亮, 形态
int leftUpCount = 0;
int rightUpCount = 0;
int leftDownCount = 0;
GraphHelper.applyRenderingHints(g2d);
if (paintHighlightGroupMarkWhenExsit(g2d, cell, leftUpCount)) {
leftUpCount++;
}
if (paintPresentMarkWhenExsit(g2d, cell, leftUpCount)) {
leftUpCount++;
}
if (paintPaginationMarkWhenExsit(g2d, cell, width, rightUpCount)) {
rightUpCount++;
}
paintWidgetMarkWhenExsit(g2d, cell, width, height);
paintExpandMarkWhenExsit(g2d, cell);
Object value = cell.getValue();
if (value == null) {// 先判断是否是空.
return;
}
if (paintResultMarkWhenExsit(g2d, value, width, rightUpCount)) {
rightUpCount++;
}
if (paintDSColumnParametermarkWhenExsit(g2d, value, height, leftDownCount)) {
leftDownCount++;
}
if (paintDSColumnConditionmarkWhenExsit(g2d, value, height, leftDownCount)) {
leftDownCount++;
}
// 画value,但因为是在Grid里面画,所以画Formula.content
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getContent();
}
if (value instanceof ImageWithSuffix) {
value = ((ImageWithSuffix) value).getFineImage();
}
if (value instanceof BaseChartCollection) {
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height);
}
// Carl:当是子报表时,在格子里画一个子报表的图
/*
* alex:TODO 此处在Grid里面画ChartCollection和SubReport都只画一个图表,这种做法,很不雅
*/
if (value instanceof ResultSubReport) {
value = BaseUtils.readImage("/com/fr/base/images/report/painter/subReport.png");
GraphHelper.paintImage(g2d, width, height, (Image) value, Constants.IMAGE_CENTER,
BaseUtils.getAlignment4Horizontal(cell.getStyle(), value), cell.getStyle().getVerticalAlignment(),
width > 16 ? 16 : width, height > 16 ? 16 : height);
} else {
renderContent(g2d, value, cell.getStyle(), width, height, resolution);
}
}
private static void renderContent(Graphics2D g2d, Object value, Style style, int width, int height, int resolution) {
if (value != null && width != 0 && height != 0) {
if (style == null) {
style = Style.DEFAULT_STYLE.deriveImageLayout(1);
}
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getResult();
}
if (value instanceof Painter) {
((Painter)value).paint(g2d, width, height, resolution, style);
} else if (value instanceof ImageProvider) {
Style.paintImageContent(g2d, ((ImageProvider) value).getImage(), style, width, height, resolution);
} else if (value instanceof Image) {
Style.paintImageContent(g2d, (Image) value, style, width, height, resolution);
} else {
String var6 = Style.valueToText(value, style.getFormat());
NewFormStyle.paintCellStyleString2(g2d, width, height, var6, style, resolution);
}
}
}
private static boolean paintHighlightGroupMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) {
if (cell.getHighlightGroup() != null && cell.getHighlightGroup().size() > 0) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_HIGHT_LIGHT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0, 0);
polyline.lineTo(0, CELL_MARK_SIZE);
polyline.lineTo(CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean paintPresentMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) {
if (cell.getPresent() != null) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PRESENT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_up_count * CELL_MARK_SIZE, 0);
polyline.lineTo(0 + left_up_count * CELL_MARK_SIZE, 6);
polyline.lineTo(CELL_MARK_SIZE + left_up_count * CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean paintPaginationMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int ringt_up_count) {
// 右上角: 标记是否有分页
if (isRightTopMarker(cell)) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PAGINATION_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, 0);
polyline.lineTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, CELL_MARK_SIZE);
polyline.lineTo(width - 1 - (ringt_up_count + 1) * CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean isRightTopMarker(TemplateCellElement cell) {
return cell.getCellPageAttr() != null && (cell.getCellPageAttr().isPageAfterColumn()
|| cell.getCellPageAttr().isPageBeforeColumn()
|| cell.getCellPageAttr().isPageAfterRow()
|| cell.getCellPageAttr().isPageBeforeRow());
}
private static boolean paintResultMarkWhenExsit(Graphics2D g2d, Object value, int width, int ringt_up_count) {
//右上角标记是否自定义显示
if (value instanceof DSColumn && ((DSColumn) value).getResult() != null) {
if (!ComparatorUtils.equals(((DSColumn) value).getResult(), "$$$")) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_RESULT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(width - ringt_up_count * CELL_MARK_SIZE - 1, 0);
polyline.lineTo(width - ringt_up_count * CELL_MARK_SIZE - 1, CELL_MARK_SIZE);
polyline.lineTo(width - (ringt_up_count + 1) * CELL_MARK_SIZE - 1, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
private static void paintWidgetMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int height) {
// 右下角:是否填报, 设置为4时,三角太小了,不知何故,设置为6
if (cell.getWidget() != null) {
Widget widget = cell.getWidget();
Image img = ((ImageIcon) ReportUtils.createWidgetIcon(widget.getClass())).getImage();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.67f));
g2d.drawImage(img, width - 15, height - 15, WIDGET_WIDTH, WIDGET_HEIGHT, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
}
}
private static void paintExpandMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell) {
CellExpandAttr cellExpandAttr = cell.getCellExpandAttr();
if (cellExpandAttr != null) {
if (cellExpandAttr.getDirection() == Constants.TOP_TO_BOTTOM) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_DIRECTION_MARK_COLOR);
GraphHelper.drawLine(g2d, 2, 0, 2, 5);
GraphHelper.drawLine(g2d, 2, 5, 0, 2);
GraphHelper.drawLine(g2d, 2, 5, 4, 2);
g2d.setPaint(oldPaint);
} else if (cellExpandAttr.getDirection() == Constants.LEFT_TO_RIGHT) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_DIRECTION_MARK_COLOR);
GraphHelper.drawLine(g2d, 0, 2, 5, 2);
GraphHelper.drawLine(g2d, 5, 2, 2, 0);
GraphHelper.drawLine(g2d, 5, 2, 2, 4);
g2d.setPaint(oldPaint);
}
}
}
private static boolean paintDSColumnConditionmarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) {
// 左下角:数据列(DSColumn)相关:比如条件过滤
if (value instanceof DSColumn && ((DSColumn) value).getCondition() != null) {
if (((DSColumn) value).getCondition() instanceof ListCondition &&
((ListCondition) ((DSColumn) value).getCondition()).getJoinConditionCount() == 0) {
// do nothing
} else {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_CONDITION_FILTER_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1);
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1);
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
private static boolean paintDSColumnParametermarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) {
// 左下角:动态注入参数
if (value instanceof DSColumn && ((DSColumn) value).getParameters() != null) {
if (((DSColumn) value).getParameters().length > 0) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PARAMETER_FILTER_MARK_CONLR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1);
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1);
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
/*
* 画悬浮元素
*
* 仅根据宽度 + 高度画
*/
//b:此方法在grid和tohtml的时候都被调用,所以对formula会有冲突,暂时这么改,应该考虑分开的,也可以根据result来判断,但是那么写好像不妥
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, int width, int height, int resolution) {
Style.paintBackground(g2d, flotEl.getStyle(), width, height);
Object value = flotEl.getValue();
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getContent();
}
if (value instanceof BaseChartCollection) {
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height);
}
//图片需要切割一下
if (value instanceof Image) {
value = CellUtils.value2ImageWithBackground(value, resolution, flotEl.getStyle(), width, height);
}
Style.paintContent(g2d, value, flotEl.getStyle(), width, height, resolution);
Style.paintBorder(g2d, flotEl.getStyle(), width, height);
}
/*
* 画悬浮元素flotEl
*
* 也就是画三个东西:背景 + 内容 + 边框
*/
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, Rectangle paintRectangle, Rectangle clipRectangle, int resolution) {
// 画悬浮元素的背景
Style.paintBackground(g2d, flotEl.getStyle(), paintRectangle, clipRectangle);
Object value = flotEl.getValue();
if (value instanceof ResultChangeWhenExport) {
value = ((ResultChangeWhenExport) value).changeThis();
}
// 画悬浮元素的内容
Style.paintContent(g2d, value, resolution, flotEl.getStyle(), paintRectangle, clipRectangle);
// 画悬浮元素的边框
Style.paintBorder(g2d, flotEl.getStyle(), paintRectangle, clipRectangle);
}
public static void paintHTMLContent(Graphics2D g2d, String value, int resolution, Style style, Rectangle paintRectangle, Rectangle clipRectangle) {
Style.paintContent(g2d, createHTMLContentBufferedImage(value, paintRectangle, 0, 0, style), resolution, style, paintRectangle, clipRectangle);
}
public static void paintTag(Painter painter, Repository repo, int width, int height, Style style, Tag tag) {
painter.paintTag(repo, width, height, style, tag);
}
/**
* 如果用户希望以HTML方式展示String这个时候先value变成图片
*
* @param value
* @param paintRectangle 绘制范围
* @param x x坐标
* @param y y坐标
* @param style 当前格子样式
* @return BufferedImage 返回图片.
*/
public static BufferedImage createHTMLContentBufferedImage(String value, Rectangle paintRectangle, int x, int y, Style style) {
return Html2ImageUtils.createHTMLContentBufferedImage(value, paintRectangle, x, y, style);
}
/**
* see <code>BaseUtils.getLineTextList</code>, 等于BaseUtils.getLineTextList().size()
* Denny: 为了提高速度和性能才单独拿出来的
* TODO: 重构
*
* @param text 文本
* @param style 样式
* @param paintWidth 单元格宽度
* @return paintWidth 单位为PT
*/
public static int getLineTextCount(String text, Style style, UNIT paintWidth) {
if (style.getRotation() != 0) {
return 1;
}
if (style.getTextStyle() != Style.TEXTSTYLE_WRAPTEXT) {
return dealNotWrapTextCount(text.toCharArray());
} else {// 自动换行
return dealWrapTextCount(text, style, paintWidth);
}
}
private static int dealNotWrapTextCount(char[] text_chars) {
boolean remain_chars = false;
int count = 0;
for (int t = 0; t < text_chars.length; t++) {
if (text_chars[t] == '\\') {// 判断是否是 "\n"
if (t + 1 < text_chars.length && text_chars[t + 1] == 'n') {
// 是"\n"字符串,但不是换行符.
t++;
count++;
if (remain_chars) {
remain_chars = false;
}
} else {
if (!remain_chars) {
remain_chars = true;
}
}
} else if (text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n')) {
count++;
if (remain_chars) {
remain_chars = false;
}
} else {
if (!remain_chars) {
remain_chars = true;
}
}
}
// 最后一个
if (remain_chars) {
count++;
}
return count;
}
// 自动换行
//neil:style里面, 默认值padding right = 2时, 默认不生效, 这边算行高时也不要计算入内
//临时处理, 去掉左边框线, 因为浏览器计算时需要考虑左边框线宽度, 但这边还是存在问题的
//同样需要考虑的是导出和web端展示, padding计算方式也不一致.
private static int dealWrapTextCount(String text, Style style, UNIT unitWidth) {
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess();
if (process != null) {
return process.getAutoChangeLineCount(text, new ObjectHolder(style), unitWidth);
}
int count = 0;
char[] text_chars = text.toCharArray();
FontMetrics fontMetrics = getFontMetrics(style);
double paintWidth = unitWidth.toPixD(Constants.FR_PAINT_RESOLUTION);
double width = paintWidth - style.getPaddingLeft() - (style.getPaddingRight() == Style.DEFAULT_PADDING ? 0 : style.getPaddingRight()) - style.getBorderLeftWidth();
boolean remain_lineText = false;
int lineTextWidth = 0;
int wordWidth = 0;
for (int t = 0, len = text_chars.length; t < len; t++) {
if (t != 0 && BaseUtils.isNumOrLetter(text_chars[t]) && BaseUtils.isNumOrLetter(text_chars[t - 1])) {
if (wordWidth + fontMetrics.charWidth(text_chars[t]) > width) {
if (lineTextWidth > 0) {
count++;
remain_lineText = false;
lineTextWidth = 0;
}
count++;
wordWidth = 0;
}
wordWidth += fontMetrics.charWidth(text_chars[t]);
} else if (isSwitchLine(text_chars, t) || isLN(text_chars, t)) {// 判断是否是 "\n"
if (isLN(text_chars, t)) {
t++;// 忽略'n'字符.// 是"\n"字符串,但不是换行符,依然需要换行.
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count += 2;
} else {
count++;
}
remain_lineText = false;
lineTextWidth = 0;
wordWidth = 0;
} else {
if (text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == '\\') {// 判断是否是转义字符'\'
t++;// _denny: 增加了转义字符'\\'用来表示\,使"\n"可以输入
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count++;
lineTextWidth = isPunctuationAtLineHead(t, text_chars) ? dealLineWidthWithPunctuation(t, text_chars, fontMetrics) : 0;
}
remain_lineText = true;
lineTextWidth += wordWidth;
wordWidth = fontMetrics.charWidth(text_chars[t]);
}
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count += 2;
} else {
count++;
}
return count;
}
/**
* 标点符号是否在换行后的行首
*/
private static boolean isPunctuationAtLineHead(int t, char[] text_chars) {
if (t > 1 && BaseUtils.isPunctuation(text_chars[t - 1])) {
return true;
}
return false;
}
/**
* 防止有连续多个标点符号要找一个非标点符号字符
*
* @date 2014-4-17
*/
private static int dealLineWidthWithPunctuation(int t, char[] text_chars, FontMetrics fontMetrics) {
if (t < 2) {
return 0;
}
int lineWidth = 0;
for (int index = t - 2; index >= 0; index--) {
lineWidth += fontMetrics.charWidth(text_chars[index]);
if (!BaseUtils.isPunctuation(text_chars[index])) {
break;
}
}
return lineWidth;
}
private static boolean isSwitchLine(char[] text_chars, int t) {
return text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n');
}
private static boolean isLN(char[] text_chars, int t) {
return text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == 'n';
}
/**
* Gets the preferred width.
*/
public static UNIT getPreferredWidth(CellElement cell, UNIT height) {
if (cell == null) {
return UNIT.ZERO;
}
Object value = cell.getShowValue();
// 只接受Text,Number,和SeparatorPainter
// got the text
if (value instanceof BaseFormula) {
if (((BaseFormula) value).getResult() != null) {
value = ((BaseFormula) value).getResult();
} else {
value = StringUtils.EMPTY;
}
}
Style style = cell.getStyle();
if (style == null) {
style = Style.DEFAULT_STYLE;
}
CellGUIAttr cg = cell.getCellGUIAttr() == null ? new CellGUIAttr() : cell.getCellGUIAttr();
value = Utils.resolveOtherValue(value, cg.isShowAsImage(), PresentationType.EXPORT);
String text = Style.valueToText(value, style.getFormat());
FontMetrics cellFM = getFontMetrics(style);
//bug 12151 有边框线的单元格 自动调整列宽 会多一行
UNIT padding = new PT(style.getPaddingLeft() + style.getPaddingRight());
if (cg.isShowAsHTML()) {
return Html2ImageUtils.getHtmlWidth(text, height, style);
}
return FU.valueOfPix(cellFM.stringWidth(text) + UNIT_SIZE, Constants.FR_PAINT_RESOLUTION).add(padding);
}
private static FontMetrics getFontMetrics(Style style) {
Font font = style.getFRFont().applyResolutionNP(Constants.FR_PAINT_RESOLUTION);
FontProcessor processor = ExtraClassManager.getInstance().getSingle(FontProcessor.MARK_STRING);
if (processor != null) {
font = processor.readExtraFont(font);
}
return GraphHelper.getFontMetrics(font);
}
/**
* Preferred height. (Got the shrink preferred height of CellElement).
* 单位格的预计算高度
*
* @param cellElement 单元格内容
* @param paintWidth 画的宽度
* @return UNIT 单位
*/
public static UNIT analyzeCellElementPreferredHeight(CellElement cellElement, UNIT paintWidth) {
// 计算高度用显示值
Object value = cellElement.getShowValue();
// 只接受Text,Number,和SeparatorPainter
Style style = cellElement.getStyle();
// got the text
if (value instanceof BaseFormula) {
if (((BaseFormula) value).getResult() != null) {
value = ((BaseFormula) value).getResult();
} else {
value = StringUtils.EMPTY;
}
}
CellGUIAttr cg = cellElement.getCellGUIAttr() == null ? new CellGUIAttr() : cellElement.getCellGUIAttr();
if (!(value instanceof String) && !(value instanceof Integer)) {
value = DataUtils.resolveOtherValue(value, cg.isShowAsImage(), cg.isShowAsDownload(), null, true);
}
String text = Style.valueToText(value, style.getFormat());
if (cg.isShowAsHTML()) {
return Html2ImageUtils.getHtmlHeight(text, paintWidth, style);
}
return PaintUtils.analyzeCellElementPreferredHeight(text, style, paintWidth, cg.isShowAsHTML());
}
/**
* 单位格的预计算高度
* 单位PT
*
* @param text 文本
* @param style 格式
* @param paintWidth 画的宽度
* @param isShowAsHtml 是否以html展示
* @return 返回 单位
*/
private static UNIT analyzeCellElementPreferredHeight(String text, Style style, UNIT paintWidth, boolean isShowAsHtml) {
if (style == null) {
//peter:获取默认的Style.
style = Style.DEFAULT_STYLE;
}
// got the text
if (text == null || text.length() <= 0) {
return PT.valueOf(0);
}
// 变成Line Text List.
if (style.getRotation() != 0) { // more easy to paint.
// attribute map.
return PT.valueOf((float) GraphHelper.stringDimensionWithRotation(text, style.getFRFont(), -style.getRotation(),
CoreConstants.DEFAULT_FRC).getHeight());
}
// 先获得FontMetics.
int lineCount = getLineTextCount(text, style, paintWidth);
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess();
if (process != null) {
//算了这两个接口分开做
return process.getLinedTextHeight(lineCount, new ObjectHolder(style));
}
// carl:和paint那边一致,添上段前段后和行间距
PT lineSpacing = PT.valueOf(style.getSpacingAfter() + style.getSpacingBefore() + style.getLineSpacing() * lineCount);
FontMetrics fontMetrics = getFontMetrics(style);
int textHeight = fontMetrics.getHeight();
FU allTextHeight = FU.valueOfPix(textHeight * lineCount, Constants.FR_PAINT_RESOLUTION);
return lineSpacing.add(allTextHeight);// 需要给底部添加Leading.
}
/**
* 截取文字只考虑了垂直方向水平方向没意义且难度大.
*
* @param value 画的值
* @param style 字体样式格式.
* @param blockArea 冻结的范围
* @param resolution 分辨率
* @return 返回的字符串
*/
public static String clipBlockValue(Object value, Style style, Rectangle primitiveArea, Rectangle blockArea, int resolution, boolean isShowAsHTML) {
if (value == null) {
return null;
}
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getResult();
}
if (blockArea.y >= primitiveArea.height || blockArea.y + blockArea.height <= 0) {
return null;
}
//截取位置,相对于clipArea
int startY = blockArea.y > 0 ? blockArea.y : 0;
int endY = blockArea.y + blockArea.height < primitiveArea.height ? blockArea.y + blockArea.height : primitiveArea.height;
if (blockArea.x >= primitiveArea.width || blockArea.x + blockArea.width <= 0) {
return null;
}
if (isShowAsHTML) {
return Html2ImageUtils.clipHtmlContent(value, style, primitiveArea, resolution, startY, endY);
}
List lineList = BaseUtils.getLineTextList((String) value, style, style.getFRFont().applyResolutionNP(resolution), primitiveArea.width, resolution);
if (lineList.isEmpty()) {
return null;
}
double spacingBefore = PT.pt2pix(style.getSpacingBefore(), resolution);
double spacingAfter = PT.pt2pix(style.getSpacingAfter(), resolution);
double lineSpacing = PT.pt2pix(style.getLineSpacing(), resolution);
double lineHeight = lineSpacing + GraphHelper.getFontMetrics(style.getFRFont().applyResolutionNP(resolution)).getHeight();
int textAllHeight = (int) (lineHeight * lineList.size() + spacingBefore + spacingAfter);
//第一行文字距区域高度
int textStartY = (int) spacingBefore;
if (style.getVerticalAlignment() == Constants.BOTTOM) {
textStartY += (primitiveArea.height - textAllHeight);
}
if (endY <= textStartY || startY >= textStartY + lineHeight * lineList.size()) {
return null;
}
int lineStart = getLineStart(lineList, lineHeight, textStartY, startY);//截取区域起始行
int lineEnd = getLineEnd(lineList, lineHeight, endY, textStartY);//截取区域结束行
String text = "";
for (; lineStart <= lineEnd; lineStart++) {
text += lineList.get(lineStart);
}
return text;
}
private static int getLineStart(List lineList, double lineHeight, int textStartY, int startY) {
int lineStart = 0;
for (int i = 0; i < lineList.size(); i++) {
if (textStartY + lineHeight * (i) <= startY && textStartY + lineHeight * (i + 1) > startY) {//压线
if (startY - textStartY - lineHeight * (i) > lineHeight / 2) {
lineStart = i + 1;
} else {
lineStart = i;
}
}
}
return lineStart;
}
private static int getLineEnd(List lineList, double lineHeight, int endY, int textStartY) {
int lineEnd = lineList.size() - 1;
for (int i = 0; i < lineList.size(); i++) {
if (textStartY + lineHeight * (i) < endY && textStartY + lineHeight * (i + 1) >= endY) {//压线
//neil:仿宋,12号字, 行间距8为例, 转为px的行间距大小为10.666, 这边算出的应该有31.98行, 因此要进位
if (endY - textStartY - lineHeight * (i) >= lineHeight / 2) {
lineEnd = i;
} else {
lineEnd = i - 1;
}
}
}
return lineEnd;
}
/**
* paintBarcode
*/
public static void paintBarcode(Graphics2D g2d, int width, int height, String text, Style style, BarcodeAttr barcodeAttr) {
BarcodeImpl barcodeImpl;
try {
barcodeImpl = BarCodeUtils.getBarcodeImpl(barcodeAttr, text);
} catch (BarcodeException exp) {
try {
//设置默认值.
barcodeImpl = BarCodeUtils.getBarcodeImpl(new BarcodeAttr(), null);
} catch (BarcodeException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return;
}
}
//字体
if (style.getFRFont() != null) {
barcodeImpl.setFont(style.getFRFont());
barcodeImpl.setForeground(style.getFRFont().getForeground());
}
//背景
Background background = style.getBackground();
if (background != null && background instanceof ColorBackground) {
barcodeImpl.setBackground(((ColorBackground) background).getColor());
}
//根据宽度和高度来确定起始点
int pointX = (width - barcodeImpl.getWidth()) / 2;
int pointY = (height - barcodeImpl.getHeight()) / 2;
barcodeImpl.draw(g2d, pointX, pointY);
}
/**
* create font attribute map, 创建属性map
*
* @param font 字体
* @return map 返回字体创建的Map
*/
public static Map createFontAttributeMap(Font font) {
Map returnFontAttributeMap = (Map) fontAttributeMapCache.get(font);
if (returnFontAttributeMap == null) {// create
// returnFontAttributeMap.
returnFontAttributeMap = font.getAttributes();
fontAttributeMapCache.put(font, returnFontAttributeMap);
}
if (font instanceof FRFont) {
FRFont frFont = (FRFont) font;
// Strikethrough
if (frFont.isStrikethrough()) {
returnFontAttributeMap.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
}
}
return returnFontAttributeMap;
}
}

27
designer-realize/src/main/java/com/fr/design/fit/AdaptiveCellElementPainter.java

@ -1,27 +0,0 @@
package com.fr.design.fit;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fit.common.PaintUtils;
import com.fr.design.mainframe.JForm;
import com.fr.grid.CellElementPainter;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.elementcase.ElementCase;
import java.awt.Graphics2D;
/**
* Created by kerry on 2020-04-21
*/
public class AdaptiveCellElementPainter extends CellElementPainter {
public void paintContent(Graphics2D g2d, ElementCase report, TemplateCellElement ce, int width, int height, int resolution) {
if (HistoryTemplateListCache.getInstance().getCurrentEditingTemplate() instanceof JForm) {
PaintUtils.paintGridCellContent(g2d, ce, width, height, resolution);
}else {
super.paintContent(g2d, report, ce, width, height, resolution);
}
}
}

21
designer-realize/src/main/java/com/fr/design/fit/NewUIModeCellElementPainter.java

@ -0,0 +1,21 @@
package com.fr.design.fit;
import com.fr.design.fit.common.NewUIModeRotationDraw;
import com.fr.grid.CellElementPainter;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.core.PaintUtils;
import com.fr.report.elementcase.ElementCase;
import java.awt.Graphics2D;
/**
* Created by kerry on 2020-04-21
*/
public class NewUIModeCellElementPainter extends CellElementPainter {
public void paintContent(Graphics2D g2d, ElementCase report, TemplateCellElement ce, int width, int height, int resolution) {
PaintUtils.paintGridCellContent(g2d, ce, width, height, resolution, new NewUIModeRotationDraw());
}
}

6
designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java

@ -9,6 +9,7 @@ import com.fr.design.actions.form.FormECFrozenAction;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
import com.fr.design.fit.NewUIModeCellElementPainter;
import com.fr.design.fit.common.FormDesignerUtil;
import com.fr.design.gui.frpane.HyperlinkGroupPane;
import com.fr.design.mainframe.*;
@ -18,6 +19,7 @@ import com.fr.design.menu.MenuDef;
import com.fr.design.menu.ShortCut;
import com.fr.design.menu.ToolBarDef;
import com.fr.design.present.ConditionAttributesGroupPane;
import com.fr.form.fit.common.LightTool;
import com.fr.form.main.Form;
import com.fr.grid.Grid;
import com.fr.grid.GridColumn;
@ -44,7 +46,9 @@ public class FormElementCasePaneDelegate extends ElementCasePane<FormElementCase
this.getGrid().setPaginateLineShowType(form.getFormMobileAttr().isMobileOnly()
? Grid.SINGLE_HORIZONTAL_PAGINATE_LINE
: Grid.NO_PAGINATE_LINE);
if (LightTool.containNewFormFlag(form)){
this.getGrid().setCellElementPainter(new NewUIModeCellElementPainter());
}
this.addSelectionChangeListener(new SelectionListener() {
@Override
public void selectionChanged(SelectionEvent e) {

12
designer-realize/src/main/java/com/fr/grid/Grid.java

@ -13,7 +13,6 @@ import com.fr.design.cell.editor.GeneralFloatEditor;
import com.fr.design.cell.editor.TextCellEditor;
import com.fr.design.constants.UIConstants;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.fit.grid.AdaptiveGridListener;
import com.fr.design.fun.GridUIProcessor;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.mainframe.DesignOperationEvent;
@ -52,7 +51,6 @@ import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Hashtable;
import java.util.Iterator;
@ -146,6 +144,8 @@ public class Grid extends BaseGridComponent {
protected int adsorbHeight;
private CellElementPainter cellElementPainter = new CellElementPainter();
public Grid(int resolution, int adsorbWidth, int adsorbHeight) {
this.resolution = resolution;
// 能触发processEvent,不管是否给component增加listener
@ -172,6 +172,14 @@ public class Grid extends BaseGridComponent {
}
public CellElementPainter getCellElementPainter() {
return cellElementPainter;
}
public void setCellElementPainter(CellElementPainter cellElementPainter) {
this.cellElementPainter = cellElementPainter;
}
public void setResolution(int resolution) {
this.resolution = resolution;
}

2
designer-realize/src/main/java/com/fr/grid/GridUI.java

@ -94,6 +94,7 @@ public class GridUI extends ComponentUI {
protected int verticalEndValue;
protected int horizontalEndValue;
protected DrawFlowRect drawFlowRect;
// paint的辅助类
protected List paintCellElementList = new ArrayList();
protected List paintCellElementRectangleList = new ArrayList();
@ -1149,6 +1150,7 @@ public class GridUI extends ComponentUI {
Graphics2D g2d = (Graphics2D) g;
Grid grid = (Grid) c;
this.painter = grid.getCellElementPainter();
// 取得ElementCasePane.ElementCase
ElementCasePane elementCasePane = grid.getElementCasePane();

Loading…
Cancel
Save