帆软报表设计器源代码。
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.
 
 
 
 

1446 lines
65 KiB

package com.fr.grid;
import com.fr.base.BaseFormula;
import com.fr.base.DynamicUnitList;
import com.fr.base.GraphHelper;
import com.fr.base.Margin;
import com.fr.base.PaperSize;
import com.fr.base.Utils;
import com.fr.base.background.ColorBackground;
import com.fr.base.background.ImageFileBackground;
import com.fr.base.iofile.attr.WatermarkAttr;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.constants.UIConstants;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.roleAuthority.ReportAndFSManagePane;
import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils;
import com.fr.general.Background;
import com.fr.general.ComparatorUtils;
import com.fr.grid.selection.CellSelection;
import com.fr.grid.selection.FloatSelection;
import com.fr.grid.selection.Selection;
import com.fr.log.FineLoggerFactory;
import com.fr.main.FineBook;
import com.fr.page.PaperSettingProvider;
import com.fr.page.ReportSettingsProvider;
import com.fr.page.WatermarkPainter;
import com.fr.page.stable.PaperSetting;
import com.fr.report.ReportHelper;
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.CellPageAttr;
import com.fr.report.core.PaintUtils;
import com.fr.report.core.ReportUtils;
import com.fr.report.elementcase.ElementCase;
import com.fr.report.elementcase.TemplateElementCase;
import com.fr.report.report.Report;
import com.fr.report.stable.ReportConstants;
import com.fr.report.stable.ReportSettings;
import com.fr.report.worksheet.FormElementCase;
import com.fr.report.worksheet.WorkSheet;
import com.fr.stable.AssistUtils;
import com.fr.stable.ColumnRow;
import com.fr.stable.Constants;
import com.fr.script.CalculatorUtils;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.UNIT;
import com.fr.third.antlr.ANTLRException;
import com.fr.third.guava.collect.HashMultimap;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Double;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
public class GridUI extends ComponentUI {
public static int INVALID_INTEGER = Integer.MIN_VALUE;// 作为不合法的数值.
protected Dimension gridSize;
protected int verticalValue;
protected int horizontalValue;
protected double paperPaintWidth;
protected double paperPaintHeight;
protected DynamicUnitList rowHeightList;
protected DynamicUnitList columnWidthList;
protected int verticalEndValue;
protected int horizontalEndValue;
protected DrawFlowRect drawFlowRect;
// paint的辅助类
protected List paintCellElementList = new ArrayList();
protected List paintCellElementRectangleList = new ArrayList();
protected List paginateLineList = new ArrayList(); // 分页线
protected HashMultimap<CellPosition, Integer> mergeCellElementTable = HashMultimap.create();
// 为了画白色的背景.
protected static Background WHITE_Backgorund = ColorBackground.getInstance(Color.WHITE);
// CellElementPainter
protected CellElementPainter painter = new CellElementPainter();
// Left
protected Rectangle2D.Double left_col_row_rect = new Rectangle2D.Double(0, 0, 0, 0);
// Top
protected Rectangle2D.Double top_col_row_rect = new Rectangle2D.Double(0, 0, 0, 0);
protected Rectangle2D.Double back_or_selection_rect = new Rectangle2D.Double(0, 0, 0, 0);
// alex:用来画拖拽中的格子的边框
protected Rectangle2D.Double drag_cell_rect = new Rectangle2D.Double(0, 0, 0, 0);
// alex:用来画单元格的白色背景,以清空原来画的内容
protected Rectangle2D.Double cell_back_rect = new Rectangle2D.Double(0, 0, 0, 0);
// 由于报表冻结的时候,当有冻结线穿过merge的格子的时候,最多需要由8个rectangle来决定.
protected Rectangle2D.Double tmpRectangle = new Rectangle2D.Double(INVALID_INTEGER,
INVALID_INTEGER, INVALID_INTEGER, INVALID_INTEGER);
protected int resolution;
private boolean isAuthority = false;
public GridUI(int resolution) {
super();
this.resolution = resolution;
}
protected ReportSettingsProvider getReportSettings(ElementCase elementCase) {
if (elementCase instanceof Report) {
return ReportUtils.getReportSettings((Report) elementCase);
} else if (elementCase instanceof FormElementCase) {
return ((FormElementCase) elementCase).getReportSettings();
} else {
return new ReportSettings();
}
}
protected void paintBackground(Graphics g, Grid grid, ElementCase elementCase, int resolution) {
Graphics2D g2d = (Graphics2D) g;
// 当前的Grid面板的大小
this.back_or_selection_rect.setRect(0, 0, gridSize.getWidth(), gridSize.getHeight());
// 需要用白色背景来清空背景.
clearBackground(g2d, grid);
// paint print dash line.
this.paperPaintWidth = 0;
this.paperPaintHeight = 0;
// richer;聚合报表设计中,最初的ElementCase还没有加到Report中,所以elementCase.getReport()可能为空
ReportSettingsProvider reportSettings = getReportSettings(elementCase);
PaperSettingProvider psetting = reportSettings.getPaperSetting();
if (psetting == null) {
psetting = new PaperSetting();
}
if (grid.getPaginateLineShowType() != Grid.NO_PAGINATE_LINE) {// paint paper margin line.
PaperSize paperSize = psetting.getPaperSize();
Margin margin = psetting.getMargin();
double paperWidth = paperSize.getWidth().toPixD(resolution);
double paperHeight = paperSize.getHeight().toPixD(resolution);
// carl:横向就反过来
if (psetting.getOrientation() == ReportConstants.LANDSCAPE) {
paperWidth = paperSize.getHeight().toPixD(resolution);
paperHeight = paperSize.getWidth().toPixD(resolution);
}
paperPaintWidth = paperWidth - margin.getLeft().toPixD(resolution)
- margin.getRight().toPixD(resolution);
paperPaintHeight = paperHeight - margin.getTop().toPixD(resolution)
- margin.getBottom().toPixD(resolution)
- reportSettings.getHeaderHeight().toPixD(resolution)
- reportSettings.getFooterHeight().toPixD(resolution);
}
// denny:画背景.Background
Background background = reportSettings.getBackground();
if (background != null && !DesignModeContext.isDuchampMode()) {
// denny: except the ColorBackground and ImageBackground
if (grid.isEnabled() && !(background instanceof ImageFileBackground)) {
background.paint(g2d, this.back_or_selection_rect);
}
// denny: make that the background can move with scroll
paintScrollBackground(g2d, grid, background, psetting, reportSettings);
}
}
private void clearBackground(Graphics2D g2d, Grid grid) {
if (grid.isEnabled()) {
g2d.setPaint(AdjustWorkBookDefaultStyleUtils.adjustBack(Color.WHITE));
} else {
g2d.setPaint(UIManager.getColor("control"));
}
GraphHelper.fill(g2d, this.back_or_selection_rect);
}
private void paintScrollBackground(Graphics2D g2d, Grid grid, Background background, PaperSettingProvider psetting, ReportSettingsProvider reportSettings) {
boolean isCanDrawImage = grid.isEditable() || isAuthority;
if (isCanDrawImage && (background instanceof ImageFileBackground)) {
if (grid.getPaginateLineShowType() == Grid.NO_PAGINATE_LINE) {
calculatePaper(psetting, reportSettings);
}
ImageFileBackground imageBackground = (ImageFileBackground) background;
int hideWidth = columnWidthList.getRangeValue(0, horizontalValue)
.toPixI(resolution);
int hideHeight = rowHeightList.getRangeValue(0, verticalValue).toPixI(resolution);
for (int i = 0; i * paperPaintWidth < gridSize.getWidth(); i++) {
for (int j = 0; j * paperPaintHeight < gridSize.getHeight(); j++) {
this.back_or_selection_rect.setRect(i * paperPaintWidth, j
* paperPaintHeight, paperPaintWidth, paperPaintHeight);
imageBackground.paint4Scroll(g2d, this.back_or_selection_rect, hideWidth,
hideHeight);
}
}
this.back_or_selection_rect
.setRect(0, 0, gridSize.getWidth(), gridSize.getHeight());
}
}
private void calculatePaper(PaperSettingProvider psetting, ReportSettingsProvider reportSettings) {
PaperSize paperSize = psetting.getPaperSize();
Margin margin = psetting.getMargin();
double paperWidth = paperSize.getWidth().toPixD(resolution);
double paperHeight = paperSize.getHeight().toPixD(resolution);
if (psetting.getOrientation() == ReportConstants.LANDSCAPE
&& paperSize.getWidth().toPixD(resolution) < paperSize.getHeight()
.toPixD(resolution)) {
paperWidth = Math.max(paperSize.getWidth().toPixD(resolution), paperSize
.getHeight().toPixD(resolution));
paperHeight = Math.min(paperSize.getWidth().toPixD(resolution), paperSize
.getHeight().toPixD(resolution));
} else if (psetting.getOrientation() == ReportConstants.PORTRAIT
&& paperSize.getWidth().toPixD(resolution) > paperSize.getHeight()
.toPixD(resolution)) {
paperWidth = Math.min(paperSize.getWidth().toPixD(resolution), paperSize
.getHeight().toPixD(resolution));
paperHeight = Math.max(paperSize.getWidth().toPixD(resolution), paperSize
.getHeight().toPixD(resolution));
}
paperPaintWidth = paperWidth - margin.getLeft().toPixD(resolution)
- margin.getRight().toPixD(resolution);
paperPaintHeight = paperHeight - margin.getTop().toPixD(resolution)
- margin.getBottom().toPixD(resolution)
- reportSettings.getHeaderHeight().toPixD(resolution)
- reportSettings.getFooterHeight().toPixD(resolution);
}
private void paintGridLine(Graphics g, Grid grid, TemplateElementCase report, double realWidth, double realHeight,
int resolution) {
Graphics2D g2d = (Graphics2D) g;
// --开始画水平,垂直线.
g2d.setPaint(grid.getGridLineColor()); // line color.
GraphHelper.setStroke(g2d, GraphHelper.getStroke(Constants.LINE_THIN));
// 分页线
paginateLineList.clear();
// 合并单元格
mergeCellElementTable.clear();
boolean isShowVerticalPaginateLine = grid.getPaginateLineShowType() == Grid.MULTIPLE_PAGINATE_LINE;
boolean isShowHorizontalPaginateLine = grid.getPaginateLineShowType() != Grid.NO_PAGINATE_LINE;
Iterator cells = report.intersect(grid.getHorizontalBeginValue(), grid.getVerticalBeginValue(),
horizontalEndValue - grid.getHorizontalBeginValue(), verticalEndValue - grid.getVerticalBeginValue());
while (cells.hasNext()) {
TemplateCellElement cellElement = (TemplateCellElement) cells.next();
if (cellElement == null) {
continue;
}
int columnSpan = cellElement.getColumnSpan();
int rowSpan = cellElement.getRowSpan();
if (columnSpan > 1 || rowSpan > 1) {
for (int c = 0; c < columnSpan - 1; c++) {
for (int r = 0; r < rowSpan; r++) {
mergeCellElementTable.put(CellPosition.value(cellElement.getRow() + r, cellElement.getColumn() + c), CellPosition.RIGHT);
}
}
for (int r = 0; r < rowSpan - 1; r++) {
for (int c = 0; c < columnSpan; c++) {
mergeCellElementTable.put(CellPosition.value(cellElement.getRow() + r, cellElement.getColumn() + c), CellPosition.BOTTOM);
}
}
}
}
int xBeginIndex = grid.getHorizontalBeginValue();
int xEndIndex = horizontalEndValue;
int yBeginIndex = grid.getVerticalBeginValue();
int yEndIndex = verticalEndValue;
if (!grid.isShowExtraGridLine()) {
xBeginIndex = 0;
xEndIndex = Math.max(0, report.getColumnCount() - 1);
yBeginIndex = 0;
yEndIndex = Math.max(0, report.getRowCount() - 1);
}
GridRange gridRange = GridRange.range(xBeginIndex, xEndIndex, yBeginIndex, yEndIndex)
.rangeList(rowHeightList, columnWidthList)
.realSize(realWidth, realHeight);
new DrawVerticalLineHelper(gridRange, grid.isShowGridLine(), grid.isShowExtraGridLine(),
isShowVerticalPaginateLine, paperPaintHeight,
paginateLineList, resolution).iterateStart2End(g2d);
new DrawHorizontalLineHelper(gridRange, grid.isShowGridLine(), grid.isShowExtraGridLine(),
isShowHorizontalPaginateLine, paperPaintWidth,
paginateLineList, resolution).iterateStart2End(g2d);
}
/**
* 最后处理
*/
@Override
public void finalize() {
try {
super.finalize();
if (drawFlowRect != null) {
this.drawFlowRect.exit();
}
} catch (Throwable e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private static abstract class DrawLineHelper {
protected GridRange gridRange;
protected boolean showGridLine;
protected boolean showExtraGridLine;
protected boolean showPaginateLine;
protected double paperPaintSize;
protected List paginateLineList;
Line2D tmpLine2D = new Line2D.Double(0, 0, 0, 0);
protected int resolution;
protected static final double THRESHOLD = 1.0E-4D;
DrawLineHelper(GridRange gridRange, boolean showGridLine, boolean showExtraGridLine,
boolean showPaginateLine, double paperPaintSize,
List paginateLineList, int resolution) {
this.gridRange = gridRange;
this.showGridLine = showGridLine;
this.showExtraGridLine = showExtraGridLine;
this.showPaginateLine = showPaginateLine;
this.paperPaintSize = paperPaintSize;
this.paginateLineList = paginateLineList;
this.resolution = resolution;
}
protected abstract void iterateStart2End(Graphics2D g2d);
protected abstract Line2D.Double getPaginateLine2D(int sumSize);
protected abstract void drawLastLine(Graphics2D g2d, int sumSize);
}
private class DrawVerticalLineHelper extends DrawLineHelper {
DrawVerticalLineHelper(GridRange gridRange, boolean showGridLine, boolean showExtraGridLine,
boolean showPaginateLine, double paperPaintSize,
List paginateLineList, int resolution) {
super(gridRange, showGridLine, showExtraGridLine, showPaginateLine,
paperPaintSize, paginateLineList, resolution);
}
@Override
protected Double getPaginateLine2D(int sumHeight) {
return new Line2D.Double(0, sumHeight, gridSize.width, sumHeight);
}
@Override
protected void drawLastLine(Graphics2D g2d, int sumHeight) {
GraphHelper.drawLine(g2d, 0, sumHeight, gridRange.realWidth, sumHeight);
}
@Override
protected void iterateStart2End(Graphics2D g2d) {
UNIT rowHeight, paperYAxisSumSize = FU.getInstance(0), maxXAxisSumSize = FU.getInstance(0), yAxisSumSize = FU.getInstance(0);
for (int i = 0; i <= gridRange.yEndIndex; i++) {
if (i == 0) {
i = gridRange.yBeginIndex;
for (int k = 0; k < gridRange.yBeginIndex; k++) {
rowHeight = gridRange.rowHeightList.get(k);
paperYAxisSumSize = paperYAxisSumSize.add(rowHeight);
if (paperYAxisSumSize.toPixF(resolution) >= paperPaintSize) {
paperYAxisSumSize = rowHeight;
}
}
}
rowHeight = gridRange.rowHeightList.get(i);
paperYAxisSumSize = paperYAxisSumSize.add(rowHeight);
if (showGridLine) {
UNIT columnWidth, xAxisSumSize = FU.getInstance(0);
for (int j = gridRange.xBeginIndex; j <= gridRange.xEndIndex; j++) {
columnWidth = gridRange.columnWidthList.get(j);
if (!mergeCellElementTable.get(CellPosition.value(i - 1, j)).contains(CellPosition.BOTTOM)) {
tmpLine2D.setLine(xAxisSumSize.toPixF(resolution), yAxisSumSize.toPixF(resolution), xAxisSumSize.add(columnWidth).toPixF(resolution), yAxisSumSize.toPixF(resolution));
g2d.draw(tmpLine2D);
}
xAxisSumSize = xAxisSumSize.add(columnWidth);
}
if (xAxisSumSize.toPixF(resolution) > maxXAxisSumSize.toPixF(resolution)) {
maxXAxisSumSize = xAxisSumSize;
}
}
if (showPaginateLine && paperYAxisSumSize.toPixF(resolution) - paperPaintSize > THRESHOLD) {
paginateLineList.add(getPaginateLine2D((int) yAxisSumSize.toPixF(resolution)));
paperYAxisSumSize = rowHeight;
}
yAxisSumSize = yAxisSumSize.add(rowHeight);
}
// paint 最后一个横线..
if (showGridLine) {
if (showExtraGridLine) {
drawLastLine(g2d, (int) yAxisSumSize.toPixF(resolution));
} else {
GraphHelper.drawLine(g2d, 0, yAxisSumSize.toPixF(resolution), maxXAxisSumSize.toPixF(resolution), yAxisSumSize.toPixF(resolution));
}
}
}
}
private class DrawHorizontalLineHelper extends DrawLineHelper {
DrawHorizontalLineHelper(GridRange gridRange, boolean showGridLine, boolean showExtraGridLine,
boolean showPaginateLine, double paperPaintSize,
List paginateLineList, int resolution) {
super(gridRange, showGridLine, showExtraGridLine, showPaginateLine,
paperPaintSize, paginateLineList, resolution);
}
@Override
protected Double getPaginateLine2D(int sumWidth) {
return new Line2D.Double(sumWidth, 0, sumWidth, gridSize.height);
}
@Override
protected void drawLastLine(Graphics2D g2d, int sumWidth) {
GraphHelper.drawLine(g2d, sumWidth, 0, sumWidth, gridRange.realHeight);
}
@Override
protected void iterateStart2End(Graphics2D g2d) {
UNIT columnWidth, paperXAxisSumSize = FU.getInstance(0), maxYAxisSumSize = FU.getInstance(0), xAxisSumSize = FU.getInstance(0);
for (int i = 0; i <= gridRange.xEndIndex; i++) {
if (i == 0) {
i = gridRange.xBeginIndex;
for (int k = 0; k < gridRange.xBeginIndex; k++) {
columnWidth = gridRange.columnWidthList.get(k);
paperXAxisSumSize = paperXAxisSumSize.add(columnWidth);
if (paperXAxisSumSize.toPixF(resolution) >= paperPaintSize) {
paperXAxisSumSize = columnWidth;
}
}
}
columnWidth = gridRange.columnWidthList.get(i);
paperXAxisSumSize = paperXAxisSumSize.add(columnWidth);
if (showGridLine) {
UNIT rowHeight, yAxisSumSize = FU.getInstance(0);
for (int j = gridRange.yBeginIndex; j <= gridRange.yEndIndex; j++) {
rowHeight = gridRange.rowHeightList.get(j);
if (!mergeCellElementTable.get(CellPosition.value(j, i - 1)).contains(CellPosition.RIGHT)) {
tmpLine2D.setLine(xAxisSumSize.toPixF(resolution), yAxisSumSize.toPixF(resolution), xAxisSumSize.toPixF(resolution), yAxisSumSize.add(rowHeight).toPixF(resolution));
g2d.draw(tmpLine2D);
}
yAxisSumSize = yAxisSumSize.add(rowHeight);
}
if (yAxisSumSize.toPixF(resolution) > maxYAxisSumSize.toPixF(resolution)) {
maxYAxisSumSize = yAxisSumSize;
}
}
if (showPaginateLine && paperXAxisSumSize.toPixF(resolution) - paperPaintSize > THRESHOLD) {
paginateLineList.add(getPaginateLine2D((int) xAxisSumSize.toPixF(resolution)));
paperXAxisSumSize = columnWidth;
}
xAxisSumSize = xAxisSumSize.add(columnWidth);
}
// paint 最后一个横线..
if (showGridLine) {
if (showExtraGridLine) {
drawLastLine(g2d, (int) xAxisSumSize.toPixD(resolution));
} else {
GraphHelper.drawLine(g2d, xAxisSumSize.toPixF(resolution), 0, xAxisSumSize.toPixF(resolution), maxYAxisSumSize.toPixF(resolution));
}
}
}
}
private void paintCellElements(Graphics g, Grid grid, TemplateElementCase report, int resolution) {
Graphics2D g2d = (Graphics2D) g;
CellElement selectedCellElement = null;
ElementCasePane reportPane = grid.getElementCasePane();
Selection sel = reportPane.getSelection();
if (sel instanceof CellSelection) {
selectedCellElement = report.getCellElement(((CellSelection) sel).getColumn(), ((CellSelection) sel).getRow());
}
int horizontalBeginValue = grid.getHorizontalBeginValue();
int verticalBeginValue = grid.getVerticalBeginValue();
// 元素数目.
Shape oldClip = null;
TemplateCellElement tmpCellElement = null;
Iterator cells = report.intersect(horizontalBeginValue, verticalBeginValue,
horizontalEndValue - horizontalBeginValue, verticalEndValue - verticalBeginValue);
// 计算隐藏掉的width
double hideWidth = columnWidthList.getRangeValue(0, horizontalValue).toPixD(resolution);
double hideHeight = rowHeightList.getRangeValue(0, verticalValue).toPixD(resolution);
// 清空left和top的绘画区域.
this.left_col_row_rect.setRect(0, 0, 0, 0);
this.top_col_row_rect.setRect(0, 0, 0, 0);
paintDetailedCellElements(g2d, cells, tmpCellElement, reportPane, selectedCellElement, hideWidth, hideHeight, oldClip, report);
paintBorder(g2d, tmpCellElement, report);
paintFatherLeft(g2d, selectedCellElement, report);
}
private void paintDetailedCellElements(Graphics2D g2d, Iterator cells, TemplateCellElement tmpCellElement, ElementCasePane reportPane,
CellElement selectedCellElement, double hideWidth, double hideHeight, Shape oldClip, TemplateElementCase report) {
while (cells.hasNext()) {
tmpCellElement = (TemplateCellElement) cells.next();
if (tmpCellElement == null) {
continue;
}
// 强制分页线
this.calculateForcedPagingOfCellElement(reportPane, tmpCellElement, hideWidth, hideHeight);
storeFatherLocation(selectedCellElement, tmpCellElement);
// element bounds
// TODO: 2017/7/13 tmpRectangle : 72*19
this.caculateScrollVisibleBounds(this.tmpRectangle, tmpCellElement.getColumn(),
tmpCellElement.getRow(), tmpCellElement.getColumnSpan(),
tmpCellElement.getRowSpan());
// peter:clip的区域.
// peter:保留clip.
oldClip = g2d.getClip(); /*
* alex:此处的tmpRectangle_1被GridUtils.validate判断必定为true,
* 因为这些tmpCellElement是intersect的结果 所以,不必判断了
*/
g2d.clip(this.tmpRectangle);
// 这边为什么要加1? 因为单元格的左边和上面有线,宽度为一,属于此单元格,画单元格的内容不应该把那条线给遮住了
g2d.translate(this.tmpRectangle.getX() + 1, this.tmpRectangle.getY() + 1);
// peter:tmpRectangle2D_3只是一个临时的Rectangle2D,由于后面不少地方需要用到这个矩形
this.cell_back_rect.setRect(0, 0, this.tmpRectangle.getWidth() - 1,
this.tmpRectangle.getHeight() - 1.5);
// peter:将这个元素添加到需要paint的元素列表当中去,留着画边框线..
paintCellElementList.add(tmpCellElement);
paintCellElementRectangleList.add(this.tmpRectangle.clone());
double cellWidth = this.tmpRectangle.getWidth();
double cellHeight = this.tmpRectangle.getHeight();
// denny_Grid: 画Grid中单元格的内容(包括单元格的背景Content + Background), 不包括边框
painter.paintBackground(g2d, report, tmpCellElement, cellWidth - 1, cellHeight - 1);
painter.paintContent(g2d, report, tmpCellElement, (int) cellWidth, (int) cellHeight, resolution);
// denny_Grid: 注意下面还要减一, 因为上面translate时加一
g2d.translate(-this.tmpRectangle.getX() - 1, -this.tmpRectangle.getY() - 1);
paintAuthorityCell(g2d, tmpCellElement);
g2d.setClip(oldClip);
}
}
private void paintAuthorityCell(Graphics2D g2d, TemplateCellElement tmpCellElement) {
String selectedRole = ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName();
boolean isWidgetAuthority = false;
if (tmpCellElement.getWidget() != null) {
isWidgetAuthority = tmpCellElement.getWidget().isDirtyWidget(selectedRole);
}
boolean isCellDoneAuthority = tmpCellElement.isDoneAuthority(selectedRole) || tmpCellElement.isDoneNewValueAuthority(selectedRole);
boolean isDoneAuthority = isWidgetAuthority || isCellDoneAuthority;
if (isAuthority && isDoneAuthority) {
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
Paint oldPaint = g2d.getPaint();
g2d.setPaint(UIConstants.AUTHORITY_COLOR);
GraphHelper.fill(g2d, tmpRectangle);
g2d.setComposite(oldComposite);
g2d.setPaint(oldPaint);
}
}
private void storeFatherLocation(CellElement selectedCellElement, TemplateCellElement tmpCellElement) {
// // 需要检查是否在Design状态隐藏.
// CellGUIAttr cellGUIAttr = tmpCellElement.getCellGUIAttr();
// if (cellGUIAttr == null) {
// // 不set给curCellElement,赋值只是为了方便下面的操作
// cellGUIAttr = CellGUIAttr.DEFAULT_CELLGUIATTR;
// }
/*
* 记录当前选中的单元格的左父与上父的位置于leftColumnRowRectangle2D &
* topColumnRowRectangle2D
*/
if (selectedCellElement == tmpCellElement) {
CellExpandAttr cellExpandAttr = tmpCellElement.getCellExpandAttr();
if (cellExpandAttr != null) {
ColumnRow leftColumnRow = cellExpandAttr.getLeftParentColumnRow();
// leftColumnRow必须在可视范围内
if (ColumnRow.validate(leftColumnRow)) {
this.caculateScrollVisibleBounds(this.left_col_row_rect,
leftColumnRow.getColumn(), leftColumnRow.getRow(), 1, 1);
}
ColumnRow topColumnRow = cellExpandAttr.getUpParentColumnRow();
// topColumnRow必须在可视范围内
if (ColumnRow.validate(topColumnRow)) {
this.caculateScrollVisibleBounds(this.top_col_row_rect,
topColumnRow.getColumn(), topColumnRow.getRow(), 1, 1);
}
}
}
}
private void paintBorder(Graphics2D g2d, TemplateCellElement tmpCellElement, TemplateElementCase report) {
// 画边框
Rectangle2D.Double tmpCellElementRectangle;
for (int i = 0; i < paintCellElementList.size(); i++) {
tmpCellElement = (TemplateCellElement) paintCellElementList.get(i);
tmpCellElementRectangle = (Rectangle2D.Double) paintCellElementRectangleList.get(i);
// 需要检查是否在Design状态隐藏.
CellGUIAttr cellGUIAttr = tmpCellElement.getCellGUIAttr();
if (cellGUIAttr == null) {
// 不set给curCellElement,赋值只是为了方便下面的操作
cellGUIAttr = CellGUIAttr.DEFAULT_CELLGUIATTR;
}
g2d.translate(tmpCellElementRectangle.getX(), tmpCellElementRectangle.getY());
painter.paintBorder(g2d, report, tmpCellElement, tmpCellElementRectangle.getWidth(),
tmpCellElementRectangle.getHeight());
g2d.translate(-tmpCellElementRectangle.getX(), -tmpCellElementRectangle.getY());
}
}
protected void paintFatherLeft(Graphics2D g2d, CellElement selectedCellElement, TemplateElementCase report) {
// 画左父格子.
if (validate(this.left_col_row_rect) && this.left_col_row_rect.getHeight() > 5) {
g2d.setPaint(Color.BLUE);
double centerX = this.left_col_row_rect.getX() + 4;
double centerY = this.left_col_row_rect.getY() + this.left_col_row_rect.getHeight() / 2;
GraphHelper.drawLine(g2d, centerX, centerY - 5, centerX, centerY + 5);
GeneralPath polyline = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
polyline.moveTo((float) centerX, (float) centerY + 5);
polyline.lineTo((float) centerX + 3, (float) centerY + 5 - 4);
polyline.lineTo((float) centerX - 2, (float) centerY + 5 - 4);
GraphHelper.fill(g2d, polyline);
}
if (validate(this.top_col_row_rect) && this.top_col_row_rect.getWidth() > 5) {
g2d.setPaint(Color.BLUE);
double centerX = this.top_col_row_rect.getX() + this.top_col_row_rect.getWidth() / 2;
double centerY = this.top_col_row_rect.getY() + 4;
GraphHelper.drawLine(g2d, centerX - 5, centerY, centerX + 5, centerY);
GeneralPath polyline = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
polyline.moveTo((float) centerX + 5, (float) centerY);
polyline.lineTo((float) centerX + 5 - 4, (float) centerY + 3);
polyline.lineTo((float) centerX + 5 - 4, (float) centerY - 3);
GraphHelper.fill(g2d, polyline);
}
}
private void paintPaginateLines(Graphics g, Grid grid) {
Graphics2D g2d = (Graphics2D) g;
// james 画分页线
if (this.paginateLineList.size() > 0) {
Line2D tmpLine2D = new Line2D.Double(0, 0, 0, 0);
// james
// 梳理forcedPaperMarginLineList,将其中相同的线去除,否则在Grid的paintConponet时会因setXORMode而将相同的线给覆盖掉
Line2D tmpLine2D2;
for (int j = 0; j < paginateLineList.size(); j++) {
tmpLine2D = (Line2D) paginateLineList.get(j);// 直接强制转换,因为List中肯定都是Line2D型的
for (int k = j + 1; k < paginateLineList.size(); k++) {
tmpLine2D2 = (Line2D) paginateLineList.get(k);
if (AssistUtils.equals(tmpLine2D2.getX1(), tmpLine2D.getX1())
&& AssistUtils.equals(tmpLine2D2.getX2(), tmpLine2D.getX2())
&& AssistUtils.equals(tmpLine2D2.getY1(), tmpLine2D.getY1())
&& AssistUtils.equals(tmpLine2D2.getY2(), tmpLine2D.getY2())) {
paginateLineList.remove(k);
}
}
}
g2d.setPaint(grid.getPaginationLineColor());
//g2d.setXORMode(Utils.getXORColor(grid.getPaginationLineColor()));
GraphHelper.setStroke(g2d, GraphHelper.getStroke(Constants.LINE_DASH_DOT));
if (grid.getPaginateLineShowType() == Grid.SINGLE_HORIZONTAL_PAGINATE_LINE) {
g2d.draw((Shape) paginateLineList.get(0));
} else {
for (int i = 0, len = paginateLineList.size(); i < len; i++) {
g2d.draw((Shape) paginateLineList.get(i));
}
}
g2d.setPaintMode();
}
}
private void paintGridSelection(Graphics g, Grid grid, ElementCase report) {
Graphics2D g2d = (Graphics2D) g;
Selection sel = grid.getElementCasePane().getSelection();
// 画GridSelection:CELL
if (sel instanceof CellSelection) {// james:cell不可以select的时候就不画了
CellSelection gridSelection = (CellSelection) sel;
// peter:开始选择框CellRectangle.
Rectangle editRectangle = gridSelection.getEditRectangle();
int cellRectangleCount = gridSelection.getCellRectangleCount();
Area selectedCellRectArea = new Area();
Area editCellRectArea = new Area();
// denny: editCellRectArea
ElementCasePane reportPane = grid.getElementCasePane();
if (DesignerContext.getFormatState() == DesignerContext.FORMAT_STATE_NULL) {
this.caculateScrollVisibleBounds(this.tmpRectangle, new Rectangle(
gridSelection.getColumn(), gridSelection.getRow(), gridSelection.getColumnSpan(), gridSelection.getRowSpan()
));
if (validate(this.tmpRectangle)) {
editCellRectArea.add(new Area(this.tmpRectangle));
}
if (cellRectangleCount == 1) {
paintOne(selectedCellRectArea, gridSelection, grid, g2d);
} else {
paintMore(selectedCellRectArea, gridSelection, grid, g2d, cellRectangleCount, editCellRectArea);
}
} else {
Rectangle referenced = null;
referenced = paintReferenceCell(reportPane, grid, g2d, editCellRectArea, selectedCellRectArea, referenced);
paintFormatArea(selectedCellRectArea, gridSelection, grid, g2d, referenced);
}
// denny: 标记公式用到的单元格
paintGridSelectionForFormula(g2d, report, gridSelection);
}
}
private Rectangle paintReferenceCell(ElementCasePane reportPane, Grid grid, Graphics2D g2d, Area editCellRectArea, Area selectedCellRectArea, Rectangle referenced) {
CellSelection referencedCell = reportPane.getFormatReferencedCell();
if (referencedCell == null) {
return null;
}
if (DesignerContext.getReferencedIndex() !=
((JTemplate) HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()).getEditingReportIndex()) {
return null;
}
referenced = new Rectangle(
referencedCell.getColumn(), referencedCell.getRow(), referencedCell.getColumnSpan(), referencedCell.getRowSpan()
);
this.caculateScrollVisibleBounds(this.tmpRectangle, referenced);
if (validate(this.tmpRectangle)) {
editCellRectArea.add(new Area(this.tmpRectangle));
}
paintOne(selectedCellRectArea, referencedCell, grid, g2d);
return referenced;
}
private void paintFormatArea(Area selectedCellRectArea, CellSelection gridSelection, Grid grid, Graphics2D g2d, Rectangle referenced) {
Rectangle format = new Rectangle(
gridSelection.getColumn(), gridSelection.getRow(), gridSelection.getColumnSpan(), gridSelection.getRowSpan()
);
if (ComparatorUtils.equals(DesignerContext.getReferencedElementCasePane(), grid.getElementCasePane()) && ComparatorUtils.equals(format, referenced)) {
return;
}
this.caculateScrollVisibleBounds(this.tmpRectangle, format);
if (validate(this.tmpRectangle)) {
selectedCellRectArea = new Area(this.tmpRectangle);
double selectedCellX = this.tmpRectangle.getX();
double selectedCellY = this.tmpRectangle.getY();
double selectedCellWidth = this.tmpRectangle.getWidth();
double selectedCellHeight = this.tmpRectangle.getHeight();
// TODO ALEX_SEP 这个半透明的,画不画呢?
// peter:画半透明的背景,必须SelectCellRectangle和EditCellRectangle不重复才需要半透明背景.
if (gridSelection.getRowSpan() > 1
|| gridSelection.getColumnSpan() > 1) {
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setPaint(grid.getSelectedBackground());
GraphHelper.fill(g2d, selectedCellRectArea);
g2d.setComposite(oldComposite);
}
paintNormal(g2d, selectedCellX, selectedCellY, selectedCellWidth, selectedCellHeight, grid);
}
}
private void paintOne(Area selectedCellRectArea, CellSelection gridSelection, Grid grid, Graphics2D g2d) {
if (validate(this.tmpRectangle)) {
selectedCellRectArea = new Area(this.tmpRectangle);
double selectedCellX = this.tmpRectangle.getX();
double selectedCellY = this.tmpRectangle.getY();
double selectedCellWidth = this.tmpRectangle.getWidth();
double selectedCellHeight = this.tmpRectangle.getHeight();
// TODO ALEX_SEP 这个半透明的,画不画呢?
// peter:画半透明的背景,必须SelectCellRectangle和EditCellRectangle不重复才需要半透明背景.
if (gridSelection.getRowSpan() > 1
|| gridSelection.getColumnSpan() > 1) {
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setPaint(grid.getSelectedBackground());
GraphHelper.fill(g2d, selectedCellRectArea);
g2d.setComposite(oldComposite);
}
// 判断是否使用智能添加单元格若使用智能添加单元格,则画动态虚线
paintGridSelectionDependsOnTableSelectionPane(g2d, selectedCellX, selectedCellY, selectedCellWidth, selectedCellHeight, grid);
}
}
private void paintMore(Area selectedCellRectArea, CellSelection gridSelection, Grid grid, Graphics2D g2d, int cellRectangleCount, Area editCellRectArea) {
selectedCellRectArea = new Area();
// cellRectangleCount > 1
// p:下面处理多个选择的情况,麻烦一些.
for (int i = 0; i < cellRectangleCount; i++) {
Rectangle cellRectangle = gridSelection.getCellRectangle(i);
// p:计算CellSelection.
this.caculateScrollVisibleBounds(this.tmpRectangle, cellRectangle);
if (validate(this.tmpRectangle)) {
selectedCellRectArea.add(new Area(this.tmpRectangle));
paintGridSelectionDependsOnTableSelectionPane(g2d, tmpRectangle.x, tmpRectangle.y, tmpRectangle.width, tmpRectangle.height, grid);
}
}
selectedCellRectArea.add(editCellRectArea);
selectedCellRectArea.exclusiveOr(editCellRectArea);
// denny: 画半透明背景
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.setPaint(grid.getSelectedBackground());
GraphHelper.fill(g2d, selectedCellRectArea);
g2d.setComposite(oldComposite);
// p:画edit空白区域的边框.
g2d.setPaint(Color.blue);
// marks:如果editCellRectArea为空,就不需要画,说明都不在可见区域内
if (editCellRectArea != null) {
GraphHelper.draw(g2d, editCellRectArea);
}
}
private void paintGridSelectionForFormula(Graphics2D g2d, ElementCase report, CellSelection cs) {
// denny: 标记公式用到的单元格
if (report.getCellValue(cs.getColumn(), cs.getRow()) instanceof BaseFormula) {
BaseFormula tmpFormula = (BaseFormula) report
.getCellValue(cs.getColumn(), cs.getRow());
String statement = tmpFormula.getContent();
// denny: 获得公式中包含的所有单元格
ColumnRow[] columnRowArray = new ColumnRow[0];
try {
columnRowArray = CalculatorUtils.relatedColumnRowArray(statement.substring(1));
} catch (ANTLRException ae) {
// do nothing.
}
Area formulaCellArea = null;
for (int i = 0; i < columnRowArray.length; i++) {
ColumnRow columnRow = columnRowArray[i];
int columnSpan = 1;
int rowSpan = 1;
CellElement columnRowCE = report.getCellElement(columnRow.getColumn(),
columnRow.getRow());
if (columnRowCE != null) {
columnSpan = columnRowCE.getColumnSpan();
rowSpan = columnRowCE.getRowSpan();
// _denny: 如果取得是合并单元格的后面的,那么需要重置columnRow
if (columnSpan > 1 || rowSpan > 1) {
columnRow = ColumnRow.valueOf(columnRowCE.getColumn(),
columnRowCE.getRow());
}
}
this.caculateScrollVisibleBounds(this.tmpRectangle, columnRow.getColumn(),
columnRow.getRow(), columnSpan, rowSpan);
if (validate(this.tmpRectangle)) {
paintFormulaCellArea(g2d, formulaCellArea, i);
}
}
}
}
protected void paintFormulaCellArea(Graphics2D g2d, Area formulaCellArea, int i) {
// denny: 标记格子的边框
formulaCellArea = new Area(new Rectangle2D.Double(this.tmpRectangle.getX(),
this.tmpRectangle.getY(), this.tmpRectangle.getWidth(),
this.tmpRectangle.getHeight()));
// peter:去掉edit的格子区域
formulaCellArea.exclusiveOr(new Area(
new Rectangle2D.Double(this.tmpRectangle.getX() + 1,
this.tmpRectangle.getY() + 1,
this.tmpRectangle.getWidth() - 2, this.tmpRectangle
.getHeight() - 2)));
formulaCellArea.add(new Area(new Rectangle2D.Double(this.tmpRectangle
.getX(), this.tmpRectangle.getY(), 3, 3)));
formulaCellArea.add(new Area(new Rectangle2D.Double(this.tmpRectangle
.getX() + this.tmpRectangle.getWidth() - 3, this.tmpRectangle
.getY(), 3, 3)));
formulaCellArea.add(new Area(new Rectangle2D.Double(this.tmpRectangle
.getX(), this.tmpRectangle.getY() + this.tmpRectangle.getHeight()
- 3, 3, 3)));
formulaCellArea.add(new Area(new Rectangle2D.Double(this.tmpRectangle
.getX() + this.tmpRectangle.getWidth() - 3, this.tmpRectangle
.getY() + this.tmpRectangle.getHeight() - 3, 3, 3)));
g2d.setPaint(new Color(((i + 2) * 50) % 256, ((i + 1) * 50) % 256,
(i * 50) % 256));
if (formulaCellArea != null) {
GraphHelper.fill(g2d, formulaCellArea);
}
}
private void paintGridSelectionDependsOnTableSelectionPane(Graphics2D g2d, double selectedCellX, double selectedCellY,
double selectedCellWidth, double selectedCellHeight, Grid grid) {
if (grid.IsNotShowingTableSelectPane()) {
// peter:构建并开始画边框,只需要对第一个Cell
paintNormal(g2d, selectedCellX, selectedCellY, selectedCellWidth, selectedCellHeight, grid);
} else {
// 动态虚线
Stroke stroke = g2d.getStroke();
g2d.setStroke(new BasicStroke(1));
if (drawFlowRect == null) {
drawFlowRect = new DrawFlowRect();
}
drawFlowRect.setGrid(grid);
drawFlowRect.drawFlowRect(g2d, (int) selectedCellX, (int) selectedCellY,
(int) selectedCellWidth + (int) selectedCellX,
(int) selectedCellHeight + (int) selectedCellY);
g2d.setStroke(stroke);
}
}
private void paintNormal(Graphics2D g2d, double selectedCellX, double selectedCellY,
double selectedCellWidth, double selectedCellHeight, Grid grid) {
this.back_or_selection_rect.setRect(selectedCellX - 1, selectedCellY - 1,
selectedCellWidth + 3, selectedCellHeight + 3);
Area borderLineArea = new Area(this.back_or_selection_rect);
this.back_or_selection_rect.setRect(selectedCellX + 2, selectedCellY + 2,
selectedCellWidth - 3, selectedCellHeight - 3);
borderLineArea.exclusiveOr(new Area(this.back_or_selection_rect));
this.back_or_selection_rect.setRect(selectedCellX + selectedCellWidth - 1,
selectedCellY + selectedCellHeight - 3, 3, 1);
borderLineArea.exclusiveOr(new Area(this.back_or_selection_rect));
this.back_or_selection_rect.setRect(selectedCellX + selectedCellWidth - 3,
selectedCellY + selectedCellHeight - 1, 1, 3);
borderLineArea.exclusiveOr(new Area(this.back_or_selection_rect));
// peter:右下角落的那个小黑方块.
this.back_or_selection_rect.setRect(selectedCellX + selectedCellWidth - 2,
selectedCellY + selectedCellHeight - 2, 5, 5);
borderLineArea.add(new Area(this.back_or_selection_rect));
//g2d.setXORMode(Utils.getXORColor(grid.getSelectedBorderLineColor()));
g2d.setPaint(grid.getSelectedBorderLineColor());
GraphHelper.fill(g2d, borderLineArea);
g2d.setPaintMode();
}
private void paintFloatElements(Graphics g, Grid grid, ElementCase report, int resolution) {
Graphics2D g2d = (Graphics2D) g;
Selection sel = grid.getElementCasePane().getSelection();
Iterator flotIt = report.floatIterator();
while (flotIt.hasNext()) {
FloatElement tmpFloatElement = (FloatElement) flotIt.next();
int lastRow = rowHeightList.getValueIndex(FU.getInstance(
tmpFloatElement.getTopDistance().toFU() + tmpFloatElement.getHeight().toFU()
));
// 限制相对位置.
if (isSuitablePosition(lastRow)) {
float floatX = columnWidthList.getRangeValue(horizontalValue, 0).toPixF(
resolution)
+ tmpFloatElement.getLeftDistance().toPixF(resolution);
float floatY = rowHeightList.getRangeValue(verticalValue, 0).toPixF(resolution)
+ tmpFloatElement.getTopDistance().toPixF(resolution);
g2d.translate(floatX, floatY);
PaintUtils.paintFloatElement(g2d, tmpFloatElement,
tmpFloatElement.getWidth().toPixI(resolution),
tmpFloatElement.getHeight().toPixI(resolution), resolution);
g2d.translate(-floatX, -floatY);
}
}
// p:画选中的悬浮元素的边框,这里必须再循环一次所有的悬浮元素,
// 因为这些方框选择点,及时这个悬浮元素被覆盖的时候,还能够选中点击的,来改变元素的尺寸的.
paintFloatElementsBorder(g2d, grid, sel, flotIt, report);
paintAuthorityFloatElement(g2d, report, ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName(), grid);
}
private boolean isSuitablePosition(int lastRow) {
// confusing logic...
return 0 >= verticalValue || 0 <= verticalEndValue || lastRow >= verticalValue
|| lastRow <= verticalValue;
}
private void paintFloatElementsBorder(Graphics2D g2d, Grid grid, Selection sel, Iterator flotIt, ElementCase report) {
// p:画选中的悬浮元素的边框,这里必须再循环一次所有的悬浮元素,
// 因为这些方框选择点,及时这个悬浮元素被覆盖的时候,还能够选中点击的,来改变元素的尺寸的.
if (sel instanceof FloatSelection) {
flotIt = report.floatIterator();
while (flotIt.hasNext()) {
FloatElement tmpFloatElement = (FloatElement) flotIt.next();
// p:如果不是选中的悬浮元素,直接continue.
if (!ComparatorUtils.equals(tmpFloatElement.getName(), ((FloatSelection) sel).getSelectedFloatName())) {
continue;
}
Rectangle2D[] rectArray = calculateFloatElementPoints(tmpFloatElement);
GraphHelper.setStroke(g2d, GraphHelper.getStroke(Constants.LINE_THIN));
for (int j = 0; j < rectArray.length; j++) {
g2d.setPaint(Utils.getXORColor(grid.getSelectedBorderLineColor()));
GraphHelper.fill(g2d, rectArray[j]);
g2d.setPaint(grid.getSelectedBorderLineColor());
GraphHelper.draw(g2d, rectArray[j]);
}
}
}
}
private Rectangle2D[] calculateFloatElementPoints(FloatElement tmpFloatElement) {
// width and height
float floatX1 = columnWidthList.getRangeValue(horizontalValue, 0).toPixF(
resolution) + tmpFloatElement.getLeftDistance().toPixF(resolution);
float floatY1 = rowHeightList.getRangeValue(verticalValue, 0).toPixF(resolution)
+ tmpFloatElement.getTopDistance().toPixF(resolution);
int floatX2 = (int) (floatX1 + tmpFloatElement.getWidth().toPixF(resolution));
int floatY2 = (int) (floatY1 + tmpFloatElement.getHeight().toPixF(resolution));
return new Rectangle2D[]{
new Rectangle2D.Double(floatX1 - 3, floatY1 - 3, 6, 6),
new Rectangle2D.Double((floatX1 + floatX2) / 2 - 3, floatY1 - 3, 6, 6),
new Rectangle2D.Double(floatX2 - 3, floatY1 - 3, 6, 6),
new Rectangle2D.Double(floatX2 - 3, (floatY1 + floatY2) / 2 - 3, 6, 6),
new Rectangle2D.Double(floatX2 - 3, floatY2 - 3, 6, 6),
new Rectangle2D.Double((floatX1 + floatX2) / 2 - 3, floatY2 - 3, 6, 6),
new Rectangle2D.Double(floatX1 - 3, floatY2 - 3, 6, 6),
new Rectangle2D.Double(floatX1 - 3, (floatY1 + floatY2) / 2 - 3, 6, 6)};
}
private void paintAuthorityFloatElement(Graphics2D g2d, ElementCase report, String selectedRoles, Grid grid) {
Iterator flotIt = report.floatIterator();
while (flotIt.hasNext()) {
FloatElement tmpFloatElement = (FloatElement) flotIt.next();
// p:如果不是选中的悬浮元素,直接continue.
if (!tmpFloatElement.getFloatPrivilegeControl().checkInvisible(selectedRoles)) {
continue;
}
float floatX1 = columnWidthList.getRangeValue(horizontalValue, 0).toPixF(
resolution) + tmpFloatElement.getLeftDistance().toPixF(resolution);
float floatY1 = rowHeightList.getRangeValue(verticalValue, 0).toPixF(resolution)
+ tmpFloatElement.getTopDistance().toPixF(resolution);
int floatX2 = (int) (floatX1 + tmpFloatElement.getWidth().toPixF(resolution));
int floatY2 = (int) (floatY1 + tmpFloatElement.getHeight().toPixF(resolution));
double x = floatX1;
double y = floatY1;
double width = floatX2 - x;
double height = floatY2 - y;
//画做过权限编辑过的悬浮元素的边框
if (isAuthority) {
paintAuthorityFloatElementBorder(g2d, x, y, width, height, grid);
}
}
}
private void paintAuthorityFloatElementBorder(Graphics2D g2d, double selectedCellX, double selectedCellY,
double selectedCellWidth, double selectedCellHeight, Grid grid) {
this.back_or_selection_rect.setRect(selectedCellX - 1, selectedCellY - 1,
selectedCellWidth + 3, selectedCellHeight + 3);
Area borderLineArea = new Area(this.back_or_selection_rect);
g2d.setXORMode(Utils.getXORColor(grid.getSelectedBorderLineColor()));
g2d.setPaint(UIConstants.AUTHORITY_COLOR);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
GraphHelper.fill(g2d, borderLineArea);
g2d.setPaintMode();
}
private void paintDragCellBorder(Graphics g, Grid grid) {
Graphics2D g2d = (Graphics2D) g;
if ((grid.getDragType() == GridUtils.DRAG_CELLSELECTION || grid.getDragType() == GridUtils.DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER)
&& (grid.getDragRectangle() != null)) {
this.caculateScrollVisibleBounds(this.drag_cell_rect, grid.getDragRectangle());
g2d.setPaint(Color.GRAY);
GraphHelper.draw(g2d, this.drag_cell_rect, Constants.LINE_THICK);
}
}
@Override
/**
* paint
*/
public void paint(Graphics g, JComponent c) {
if (!(c instanceof Grid)) {
throw new IllegalArgumentException("The component c to paint must be a Grid!");
}
isAuthority = DesignerMode.isAuthorityEditing();
Graphics2D g2d = (Graphics2D) g;
Grid grid = (Grid) c;
// 取得ElementCasePane.ElementCase
ElementCasePane elementCasePane = grid.getElementCasePane();
TemplateElementCase elementCase = elementCasePane.getEditingElementCase();// 取出ElementCase对象
dealWithSizeBeforePaint(grid, elementCase);
double realWidth = gridSize.getWidth();// 宽度
double realHeight = gridSize.getHeight();// 高度
if (!grid.isTranslucent()) {
// 画背景
this.paintBackground(g2d, grid, elementCase, resolution);
}
// 画Grid Line
this.paintGridLine(g2d, grid, elementCase, realWidth, realHeight, resolution);
// peter:添上线程的支持,有时候,paint元素的时候,可能会有元素被删除了.
// 需要先清除画Border需要的元素.
paintCellElementList.clear();
paintCellElementRectangleList.clear();
// 画单元格元素
this.paintCellElements(g2d, grid, elementCase, resolution);
// 画分页线
this.paintPaginateLines(g2d, grid);
// 画 GridSelection
if (!(isAuthority && elementCase instanceof WorkSheet && !((WorkSheet) elementCase).isPaintSelection())) {
this.paintGridSelection(g2d, grid, elementCase);
}
// 画悬浮元素
this.paintFloatElements(g2d, grid, elementCase, resolution);
// 画Drag格子的边框.
this.paintDragCellBorder(g2d, grid);
// 画水印
if (elementCase instanceof WorkSheet) {
paintWatermark(g2d, ((WorkSheet) elementCase).getBook());
}
grid.ajustEditorComponentBounds(); // refresh size
}
// 绘制水印
private void paintWatermark(Graphics2D g2d, FineBook book) {
WatermarkAttr watermark = ReportUtils.getWatermarkAttrFromTemplateAndGlobal(book);
WatermarkPainter painter = WatermarkPainter.createPainter(watermark, resolution);
painter.paint(g2d, gridSize.width, gridSize.height);
}
private void dealWithSizeBeforePaint(Grid grid, TemplateElementCase elementCase) {
// 取出所有的行高和列宽的List
this.rowHeightList = ReportHelper.getRowHeightList(elementCase);
this.columnWidthList = ReportHelper.getColumnWidthList(elementCase);
this.verticalValue = grid.getVerticalValue();
this.horizontalValue = grid.getHorizontalValue();
int verticalExtent = grid.getVerticalExtent();
int horizontalExtent = grid.getHorizontalExtent();
// denny: set the verticalBeginValue and horizontalBeginValue
grid.setVerticalBeinValue(verticalValue);
grid.setHorizontalBeginValue(horizontalValue);
// denny: end
// 获得控件的实际尺寸
this.gridSize = grid.getSize();
this.verticalEndValue = verticalValue + verticalExtent + 1;
this.horizontalEndValue = horizontalValue + horizontalExtent + 1;
}
/**
* 计算单元格可见的边框范围
*
* @param rect 用于计算的rect
* @param cellElement 单元格
*/
public void caculateScrollVisibleBounds(Rectangle2D.Double rect, CellElement cellElement) {
caculateScrollVisibleBounds(rect, cellElement.getColumn(), cellElement.getRow(),
cellElement.getColumnSpan(), cellElement.getRowSpan());
}
/**
* 计算矩形可见的边框范围
*
* @param rect 用于计算的rect
* @param target 目标矩形
*/
public void caculateScrollVisibleBounds(Rectangle2D.Double rect, Rectangle target) {
caculateScrollVisibleBounds(rect, target.x, target.y, target.width, target.height);
}
/**
* 计算(int column,int row,int columnSpan,int rowSpan,),在Grid控件上面的位置.
* 注意:返回的paintRectangle和clipRectangle不能为null,来区别是否不需要paint或者没有clip.
* 因为这个方法用在Grid里面,为了加快Grid的paint速度,不能不停的new Rectangle()来增加内存的消耗.
* <p/>
* 处理过的tmpRectangle2Ds必须经过validate的处理才可以使用!!
*
* @param rect rect是一个长度为8的Rectangle2D数组, 绘画的区域不可见 paintRectangle.x =INVALID_INTEGER
* @param column 列
* @param row 行
* @param columnSpan 列数
* @param rowSpan 行数
*/
public void caculateScrollVisibleBounds(Rectangle2D.Double rect, int column, int row,
int columnSpan, int rowSpan) {
// 判断是否在不可见的区域.
if (outOfScreen(column, row, columnSpan, rowSpan)) {
// 如果在屏幕之外,变成INVALID_INTEGER
rect.x = INVALID_INTEGER;
} else {
rect.x = (columnWidthList.getRangeValue(horizontalValue, column))
.toPixD(resolution);
rect.y = (rowHeightList.getRangeValue(verticalValue, row)).toPixD(resolution);
rect.width = (columnWidthList.getRangeValue(column, column + columnSpan))
.toPixD(resolution);
rect.height = (rowHeightList.getRangeValue(row, row + rowSpan)).toPixD(resolution);
}
}
private boolean outOfScreen(int column, int row, int columnSpan, int rowSpan) {
return column > horizontalEndValue || row > verticalEndValue
|| column + columnSpan <= horizontalValue || row + rowSpan <= verticalValue;
}
/**
* 是否有效的Rectangle2D
*
* @param rect 目标rect
* @return 有效返回true
*/
public static boolean validate(Rectangle2D rect) {
return rect != null && !ComparatorUtils.equals(rect.getX(), INVALID_INTEGER);
}
/**
* double frozenHeight从顶部到冻结窗口的格子高度
*
* @param reportPane 用于计算的单元格面板
* @param tmpCellElement 用于计算的element
* @param hideWidth 由于冻结窗口或滚动条滚动隐藏了的总宽度 double
* @param hideHeight 由于冻结窗口或滚动条滚动隐藏了的总高度 double frozenWidth;//从左侧到冻结窗口的格子宽度
*/
public void calculateForcedPagingOfCellElement(ElementCasePane reportPane,
CellElement tmpCellElement, double hideWidth, double hideHeight) {
if (tmpCellElement == null) {
return;
}
// 找出所有需要paint的强制分页线
CellPageAttr cellPageAttr = tmpCellElement.getCellPageAttr();
if (cellPageAttr == null) {
return;
}
ElementCase report = reportPane.getEditingElementCase();
DynamicUnitList columnWidthList = ReportHelper.getColumnWidthList(report);
DynamicUnitList rowHeightList = ReportHelper.getRowHeightList(report);
int width = reportPane.getSize().width;
int height = reportPane.getSize().height;
double sumWidth;// 分页线的起始x位置
double sumHeight;// 分页线的起始y位置
if (cellPageAttr.isPageAfterColumn()) {
sumWidth = columnWidthList.getRangeValueFromZero(
tmpCellElement.getColumn() + tmpCellElement.getColumnSpan()).toPixD(resolution)
- hideWidth;
paginateLineList.add(new Line2D.Double(sumWidth, 0, sumWidth, height));
}
if (cellPageAttr.isPageBeforeColumn()) {
sumWidth = columnWidthList.getRangeValueFromZero(tmpCellElement.getColumn()).toPixD(
resolution)
- hideWidth;
paginateLineList.add(new Line2D.Double(sumWidth, 0, sumWidth, height));
}
if (cellPageAttr.isPageAfterRow()) {
sumHeight = rowHeightList.getRangeValueFromZero(
tmpCellElement.getRow() + tmpCellElement.getRowSpan()).toPixD(resolution)
- hideHeight;
paginateLineList.add(new Line2D.Double(0, sumHeight, width, sumHeight));
}
if (cellPageAttr.isPageBeforeRow()) {
sumHeight = rowHeightList.getRangeValueFromZero(tmpCellElement.getRow()).toPixD(
resolution)
- hideHeight;
paginateLineList.add(new Line2D.Double(0, sumHeight, width, sumHeight));
}
}
/**
* 描述单元格位置的POJO
*/
private static class CellPosition {
public final static int TOP = 0;
public static final int LEFT = 1;
public final static int BOTTOM = 2;
public static final int RIGHT = 4;
public int x;
public int y;
public CellPosition(int x, int y) {
this.x = x;
this.y = y;
}
public static CellPosition value(int x, int y) {
return new CellPosition(x, y);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CellPosition that = (CellPosition) o;
return x == that.x && y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
/**
* 描述表格范围的POJO
* x轴为水平方向,对应的宽度表为列宽列表
* y轴为垂直方向,对应的宽度表为行高列表
*/
private static class GridRange {
public int xBeginIndex;
public int xEndIndex;
public int yBeginIndex;
public int yEndIndex;
double realWidth;
double realHeight;
/**
* 行高列表,对应y方向线段
*/
public DynamicUnitList rowHeightList;
/**
* 列宽列表,对应x方向线段
*/
public DynamicUnitList columnWidthList;
public GridRange(int xBeginIndex, int xEndIndex, int yBeginIndex, int yEndIndex) {
this.xBeginIndex = xBeginIndex;
this.xEndIndex = xEndIndex;
this.yBeginIndex = yBeginIndex;
this.yEndIndex = yEndIndex;
}
/**
* 设置行高列宽列表
*
* @param rowHeightList 行高列表
* @param columnWidthList 列宽列表
*/
public GridRange rangeList(DynamicUnitList rowHeightList, DynamicUnitList columnWidthList) {
this.rowHeightList = rowHeightList;
this.columnWidthList = columnWidthList;
return this;
}
/**
* 设置表格真实宽高
*
* @param realWidth 宽度
* @param realHeight 高度
*/
public GridRange realSize(double realWidth, double realHeight) {
this.realWidth = realWidth;
this.realHeight = realHeight;
return this;
}
public static GridRange range(int xBeginIndex, int xEndIndex, int yBeginIndex, int yEndIndex) {
return new GridRange(xBeginIndex, xEndIndex, yBeginIndex, yEndIndex);
}
}
}