package com.fr.grid; import com.fr.base.DynamicUnitList; import com.fr.base.ScreenResolution; import com.fr.design.cell.clipboard.CellElementsClip; import com.fr.design.cell.clipboard.ElementsTransferable; import com.fr.design.cell.clipboard.FloatElementsClip; import com.fr.design.mainframe.ElementCasePane; import com.fr.design.mainframe.JSliderPane; import com.fr.design.utils.gui.GUICoreUtils; 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.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.CellGUIAttr; import com.fr.report.core.PaintUtils; import com.fr.report.elementcase.ElementCase; import com.fr.report.elementcase.TemplateElementCase; import com.fr.report.stable.ReportConstants; import com.fr.stable.ColumnRow; import com.fr.stable.unit.FU; import com.fr.stable.unit.PT; import com.fr.stable.unit.UNIT; import java.awt.*; import java.awt.geom.Rectangle2D; import java.util.Iterator; /** * Some util method of GUI. */ public class GridUtils { private GridUtils() { } //peter:没有Drag public final static int DRAG_NONE = 0; //peter:Drag CellSelection的边框来移动元素. public final static int DRAG_CELLSELECTION = 1; //peter:Drag CellSelection的右下角落来复制元素 public final static int DRAG_CELLSELECTION_BOTTOMRIGHT_CORNER = 2; public final static int DRAG_FLOAT = 3; //peter:下面这几个量是在Drag列的时候用. public final static int DRAG_CELL_SIZE = 1; //peter:drag的时候改变格子的宽度. public final static int DRAG_SELECT_UNITS = 2; //peter:drag的时候,选中单元格. // public static int resolution = (int) (ScreenResolution.getScreenResolution()* JSliderPane.getInstance().resolutionTimes); /** * Is above float element.(the return may be null).
* The length of Object[] is 2, the first is FloatElement, the second is Cursor.
* The object[] is null */ public static Object[] getAboveFloatElementCursor(ElementCasePane reportPane, double evtX, double evtY) { //peter: 将要返回的Objects Object[] returnObject = null; ElementCase report = reportPane.getEditingElementCase(); Selection sel = reportPane.getSelection(); //peter:检查所有的悬浮元素. Iterator flotIt = report.floatIterator(); while (flotIt.hasNext()) { FloatElement tmpFloatElement = (FloatElement) flotIt.next(); int resolution = reportPane.getGrid().getResolution(); //peter:计算悬浮元素的四个角落的位置. double[] floatArray = caculateFloatElementLocations_withresolution(tmpFloatElement, ReportHelper.getColumnWidthList(report), ReportHelper.getRowHeightList(report), reportPane.getGrid().getVerticalValue(), reportPane.getGrid().getHorizontalValue(), resolution); //peter:悬浮元素的范围. Rectangle2D floatElementRect = new Rectangle2D.Double(floatArray[0], floatArray[1], tmpFloatElement.getWidth().toPixD(resolution), tmpFloatElement.getHeight().toPixD(resolution)); //peter:不是当前选中的悬浮元素,不支持六个改变大小的点. if (!(sel instanceof FloatSelection && ComparatorUtils.equals(tmpFloatElement.getName(), ((FloatSelection) sel).getSelectedFloatName()))) { if (floatElementRect.contains(evtX, evtY)) { returnObject = new Object[]{tmpFloatElement, new Cursor(Cursor.MOVE_CURSOR)}; } //peter:还要继续查找,如果当前的鼠标在选中的悬浮元素的六个可以移动的点上,优先. continue; } Cursor cursor = null; Rectangle2D[] cornerRect = getCornerRect(floatArray); //peter:悬浮元素对应的六种鼠标. int[] cursorType = {Cursor.NW_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR, Cursor.E_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR}; for (int c = 0; c < cornerRect.length; c++) { if (cornerRect[c].contains(evtX, evtY)) { cursor = new Cursor(cursorType[c]); break; } } //peter:在悬浮元素区域内部,但是不在那六个点上,是移动的鼠标 if (floatElementRect.contains(evtX, evtY) && cursor == null) { returnObject = new Object[]{tmpFloatElement, new Cursor(Cursor.MOVE_CURSOR)}; } //peter:在当前选中元素的六个点上,最高优先级别,直接返回. if (cursor != null) {// select return new Object[]{tmpFloatElement, cursor}; } } return returnObject; } //peter:悬浮元素的六个可移动的小矩形点. //marks:当选择的悬浮元素多余一个时候,我们应该不返回悬浮元素的光标 private static Rectangle2D[] getCornerRect(double[] floatArray) { double floatX1 = floatArray[0]; double floatY1 = floatArray[1]; double floatX2 = floatArray[2]; double floatY2 = floatArray[3]; Rectangle2D[] cornerRect = {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)}; return cornerRect; } /** * Gets float element locations. Returns[] {flaotX1, floatY1, floatX2, floatY2}. */ public static double[] caculateFloatElementLocations(FloatElement floatElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList, int verticalValue, int horizentalValue) { // int resolution = ScreenResolution.getScreenResolution(); int resolution = (int) (ScreenResolution.getScreenResolution() * JSliderPane.getInstance().resolutionTimes); double floatX = columnWidthList.getRangeValue(horizentalValue, 0).toPixD(resolution) + floatElement.getLeftDistance().toPixD(resolution); double floatY = rowHeightList.getRangeValue(verticalValue, 0).toPixD(resolution) + floatElement.getTopDistance().toPixD(resolution); double floatX2 = floatX + floatElement.getWidth().toPixD(resolution); double floatY2 = floatY + floatElement.getHeight().toPixD(resolution); return new double[]{floatX, floatY, floatX2, floatY2}; } public static double[] caculateFloatElementLocations_withresolution(FloatElement floatElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList, int verticalValue, int horizentalValue, int resolution) { double floatX = columnWidthList.getRangeValue(horizentalValue, 0).toPixD(resolution) + floatElement.getLeftDistance().toPixD(resolution); double floatY = rowHeightList.getRangeValue(verticalValue, 0).toPixD(resolution) + floatElement.getTopDistance().toPixD(resolution); double floatX2 = floatX + floatElement.getWidth().toPixD(resolution); double floatY2 = floatY + floatElement.getHeight().toPixD(resolution); return new double[]{floatX, floatY, floatX2, floatY2}; } /** * Gets column and row which located on (evtX, evtY) * peter:这个方法重复考虑到Frozen的情况,没有任何BUG,这个方法没有考虑那种不无限增大的情况. * * @param reportPane 当前的ReportPane * @param evtX event x * @param evtY event y * @return the event located column and row. */ public static ColumnRow getEventColumnRow(ElementCasePane reportPane, double evtX, double evtY) { ElementCase report = reportPane.getEditingElementCase(); // Width and height list. DynamicUnitList rowHeightList = ReportHelper.getRowHeightList(report); DynamicUnitList columnWidthList = ReportHelper.getColumnWidthList(report); int verticalValue = reportPane.getGrid().getVerticalValue(); int horizentalValue = reportPane.getGrid().getHorizontalValue(); // denny: get verticalBeginValue and horizontalBeginValue; int verticalBeginValue = reportPane.getGrid().getVerticalBeginValue(); int horizontalBeginValue = reportPane.getGrid().getHorizontalBeginValue(); return ColumnRow.valueOf( cc_selected_column_or_row(evtX, horizontalBeginValue, horizentalValue, columnWidthList), cc_selected_column_or_row(evtY, verticalBeginValue, verticalValue, rowHeightList) ); } private static int cc_selected_column_or_row(double mouseEvtPosition, int beginValue, int value, DynamicUnitList sizeList) { double tmpIntIndex = 0; int selectedCellIndex = 0; // int resolution = ScreenResolution.getScreenResolution(); int resolution = (int) (ScreenResolution.getScreenResolution() * JSliderPane.getInstance().resolutionTimes); if (mouseEvtPosition < 0) { selectedCellIndex = value; for (; true; selectedCellIndex--) { if (tmpIntIndex < mouseEvtPosition) { break; } tmpIntIndex -= sizeList.get(selectedCellIndex).toPixD(resolution); } } else { boolean isInnerFrozen = false; for (int i = beginValue; i < 0; i++) { tmpIntIndex += sizeList.get(i).toPixD(resolution); if (tmpIntIndex > mouseEvtPosition) { selectedCellIndex = i; isInnerFrozen = true; break; } } if (!isInnerFrozen) { selectedCellIndex = value; for (; true; selectedCellIndex++) { tmpIntIndex += sizeList.get(selectedCellIndex).toPixD(resolution); if (tmpIntIndex > mouseEvtPosition) { break; } } } } return selectedCellIndex; } public static ColumnRow getEventColumnRow_withresolution(ElementCasePane reportPane, double evtX, double evtY, int resolution) { ElementCase report = reportPane.getEditingElementCase(); // Width and height list. DynamicUnitList rowHeightList = ReportHelper.getRowHeightList(report); DynamicUnitList columnWidthList = ReportHelper.getColumnWidthList(report); int verticalValue = reportPane.getGrid().getVerticalValue(); int horizentalValue = reportPane.getGrid().getHorizontalValue(); // denny: get verticalBeginValue and horizontalBeginValue; int verticalBeginValue = reportPane.getGrid().getVerticalBeginValue(); int horizontalBeginValue = reportPane.getGrid().getHorizontalBeginValue(); return ColumnRow.valueOf( cc_selected_column_or_row_withresolution(evtX, horizontalBeginValue, horizentalValue, columnWidthList, resolution), cc_selected_column_or_row_withresolution(evtY, verticalBeginValue, verticalValue, rowHeightList, resolution) ); } private static int cc_selected_column_or_row_withresolution(double mouseEvtPosition, int beginValue, int value, DynamicUnitList sizeList, int resolution) { double tmpIntIndex = 0; int selectedCellIndex = 0; // int resolution = ScreenResolution.getScreenResolution(); if (mouseEvtPosition < 0) { selectedCellIndex = value; for (; true; selectedCellIndex--) { if (tmpIntIndex < mouseEvtPosition) { break; } tmpIntIndex -= sizeList.get(selectedCellIndex).toPixD(resolution); } } else { boolean isInnerFrozen = false; for (int i = beginValue; i < 0; i++) { tmpIntIndex += sizeList.get(i).toPixD(resolution); if (tmpIntIndex > mouseEvtPosition) { selectedCellIndex = i; isInnerFrozen = true; break; } } if (!isInnerFrozen) { selectedCellIndex = value; for (; true; selectedCellIndex++) { tmpIntIndex += sizeList.get(selectedCellIndex).toPixD(resolution); if (tmpIntIndex > mouseEvtPosition) { break; } } } } return selectedCellIndex; } /** * Gets column and row which located on (evtX, evtY) * peter:这个方法是调整过的Column,Row,不能小于0, 不能大于最大值,这个方法充分考虑了不无限增大的情况. * 一般经常用这个方法, 对应的getEventColumnRow(...)反而不常用. * * @param reportPane 当前的ReportPane * @param evtX event x * @param evtY event y * @return the event located column and row. */ public static ColumnRow getAdjustEventColumnRow(ElementCasePane reportPane, double evtX, double evtY) { ColumnRow selectedCellPoint = GridUtils.getEventColumnRow(reportPane, evtX, evtY); int col = Math.max(selectedCellPoint.getColumn(), 0); int row = Math.max(selectedCellPoint.getRow(), 0); return ColumnRow.valueOf(col, row); } public static ColumnRow getAdjustEventColumnRow_withresolution(ElementCasePane reportPane, double evtX, double evtY, int resolution) { ColumnRow selectedCellPoint = GridUtils.getEventColumnRow_withresolution(reportPane, evtX, evtY, resolution); int col = Math.max(selectedCellPoint.getColumn(), 0); int row = Math.max(selectedCellPoint.getRow(), 0); return ColumnRow.valueOf(col, row); } /** * 是否可将当前单元格变为可见的格子 */ public static boolean canMove(ElementCasePane reportPane, int cellColumn, int cellRow) { if (reportPane.mustInVisibleRange()) { Grid grid = reportPane.getGrid(); int verticalEndValue = grid.getVerticalValue() + grid.getVerticalExtent() - 1; int horizontalEndValue = grid.getHorizontalValue() + grid.getHorizontalExtent() - 1; if (cellColumn > horizontalEndValue) { return false; } if (cellRow > verticalEndValue) { return false; } } return true; } /** * 选择一个Cell, 支持Merge. */ public static void doSelectCell(ElementCasePane reportPane, int cellColumn, int cellRow) { ElementCase report = reportPane.getEditingElementCase(); CellElement cellElement = report.getCellElement(cellColumn, cellRow); if (cellElement == null) { reportPane.setSelection(new CellSelection(cellColumn, cellRow, 1, 1)); } else { reportPane.setSelection(new CellSelection(cellElement.getColumn(), cellElement.getRow(), cellElement.getColumnSpan(), cellElement.getRowSpan())); } } /** * peter: 从ReportPane选中的区域产生ElementsCopy */ public static ElementsTransferable caculateElementsTransferable(ElementCasePane reportPane) { ElementsTransferable elementsTransferable = new ElementsTransferable(); //p:获得当前的Report对象. ElementCase report = reportPane.getEditingElementCase(); Selection sel = reportPane.getSelection(); //p:先判断悬浮元素. if (sel instanceof FloatSelection) { FloatSelection fs = (FloatSelection) sel; //p:需要构建floatElementsClip. FloatElementsClip floatElementsClip = new FloatElementsClip(report.getFloatElement(fs.getSelectedFloatName())); elementsTransferable.addObject(floatElementsClip); } else { CellSelection cs = (CellSelection) sel; java.util.List elList = new java.util.ArrayList(); //p:获得所有相交的CellElement. Rectangle selectionBounds = new Rectangle(cs.getColumn(), cs.getRow(), cs.getColumnSpan(), cs.getRowSpan()); Iterator cells = report.intersect(cs.getColumn(), cs.getRow(), cs.getColumnSpan(), cs.getRowSpan()); while (cells.hasNext()) { TemplateCellElement cellElement = (TemplateCellElement) cells.next(); Rectangle tmpCellBound = new Rectangle(cellElement.getColumn(), cellElement.getRow(), cellElement.getColumnSpan(), cellElement.getRowSpan()); //peter,相等或者包含 if (GUICoreUtils.isTheSameRect(selectionBounds, tmpCellBound) || selectionBounds.contains(tmpCellBound)) { //peter:添加到CellElementsClip elList.add((TemplateCellElement) cellElement.deriveCellElement(cellElement.getColumn() - cs.getColumn(), cellElement.getRow() - cs.getRow())); } } elementsTransferable.addObject(new CellElementsClip( cs.getColumnSpan(), cs.getRowSpan(), elList.toArray(new TemplateCellElement[elList.size()]) )); } return elementsTransferable; } /** * james: Gets adjust last columrow of reportpane especially used in whole row/column selected * the area before last columnrow should contain all the cellelement of the reportpane */ public static ColumnRow getAdjustLastColumnRowOfReportPane(ElementCasePane reportPane) { ElementCase report = reportPane.getEditingElementCase(); //james:全选到最后一个有内容的格子 return ColumnRow.valueOf(Math.max(1, report.getColumnCount()), Math.max(1, report.getRowCount())); } /** * 计算可见区域的行/列数 */ public static int getExtentValue(int start, DynamicUnitList sizeList, double visibleSize, int dpi) { double sumSize = 0; int maxIndex = Integer.MAX_VALUE; for (int i = start; i <= maxIndex; i++) { sumSize += sizeList.get(i).toPixD(dpi); if (sumSize > visibleSize) { start = i; // check zero value. for (int j = i; true; j++) { if (sizeList.get(j).equal_zero()) { start = j; } else { break; } } break; } } return start; } public static void shrinkToFit(int reportShrinkMode, TemplateElementCase tplEC, TemplateCellElement editCellElement) { DynamicUnitList columnWidthList = ReportHelper.getColumnWidthList(tplEC); DynamicUnitList rowHeightList = ReportHelper.getRowHeightList(tplEC); CellGUIAttr cellGUIAttr = editCellElement.getCellGUIAttr(); if (cellGUIAttr == null) { cellGUIAttr = new CellGUIAttr(); } // carl:根据用户设置来调整行高或者列宽 if (cellGUIAttr.getAdjustMode() == ReportConstants.AUTO_SHRINK_TO_FIT_HEIGHT || (cellGUIAttr.getAdjustMode() == ReportConstants.AUTO_SHRINK_TO_FIT_DEFAULT && reportShrinkMode == ReportConstants.AUTO_SHRINK_TO_FIT_HEIGHT)) { fitHetght(editCellElement, columnWidthList, rowHeightList); } else if (cellGUIAttr.getAdjustMode() == ReportConstants.AUTO_SHRINK_TO_FIT_WIDTH || (cellGUIAttr.getAdjustMode() == ReportConstants.AUTO_SHRINK_TO_FIT_DEFAULT && reportShrinkMode == ReportConstants.AUTO_SHRINK_TO_FIT_WIDTH)) { fitWidth(editCellElement, columnWidthList, rowHeightList); } } private static void fitHetght(TemplateCellElement editCellElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList) { int editElementcolumn = editCellElement.getColumn(); UNIT preferredHeight = PaintUtils.analyzeCellElementPreferredHeight( editCellElement, columnWidthList.getRangeValue(editElementcolumn, editElementcolumn + editCellElement.getColumnSpan())); if (editCellElement.getRowSpan() == 1) { rowHeightList.set(editCellElement.getRow(), UNIT.max(preferredHeight, rowHeightList.get(editCellElement.getRow()))); } else { int lastRowIndex = editCellElement.getRow() + editCellElement.getRowSpan() - 1; // kurt 画单元格时增加的高度 long extraHeight = preferredHeight.toFU() - rowHeightList.getRangeValue(editCellElement.getRow(), lastRowIndex + 1).toFU(); if (extraHeight > 0) { // kurt 平分给这些行 for (int m = editCellElement.getRow(); m <= lastRowIndex; m++) { rowHeightList.set(m, FU.getInstance(rowHeightList.get(m).toFU() + extraHeight / editCellElement.getRowSpan())); } } } } private static void fitWidth(TemplateCellElement editCellElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList) { UNIT preferredWidth = PaintUtils.getPreferredWidth(editCellElement, PT.valueOfFU(rowHeightList.getRangeValue(editCellElement.getRow(), editCellElement.getRow() + editCellElement.getRowSpan()).toFU())); // carl:照着调整行高来弄 if (editCellElement.getColumnSpan() == 1) { columnWidthList.set(editCellElement.getColumn(), UNIT.max(preferredWidth, columnWidthList.get(editCellElement.getColumn()))); } else { int lastColumnIndex = editCellElement.getColumn() + editCellElement.getColumnSpan() - 1; long extraWidth = preferredWidth.toFU() - columnWidthList.getRangeValue(editCellElement.getColumn(), lastColumnIndex + 1).toFU(); if (extraWidth > 0) { for (int m = editCellElement.getColumn(); m <= lastColumnIndex; m++) { columnWidthList.set(m, FU.getInstance(columnWidthList.get(m).toFU() + extraWidth / editCellElement.getColumnSpan() + 1)); } } } } }