Browse Source

Pull request #5251: REPORT-55060 数据集预览支持复制

Merge in DESIGN/design from ~HENRY.WANG/design:feature/10.0 to feature/10.0

* commit 'ebf44c29a8bf51664783a0aeab79bb890931d68e':
  REPORT-55060 数据集预览支持复制
  REPORT-55060 数据集预览支持复制
  REPORT-55060 数据集预览支持复制
feature/10.0
Henry.Wang 3 years ago
parent
commit
2693a17f21
  1. 24
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardHelper.java
  2. 203
      designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java
  3. 3
      designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java
  4. 203
      designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java

24
designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardHelper.java

@ -0,0 +1,24 @@
package com.fr.design.base.clipboard;
import java.util.List;
public class ClipboardHelper {
public static String formatExcelString(List<List<Object>> table) {
StringBuffer stringBuffer = new StringBuffer();
for (int row = 0; row < table.size(); row++) {
List<Object> rowValue = table.get(row);
for (int col = 0; col < rowValue.size(); col++) {
Object cell = rowValue.get(col);
stringBuffer.append(cell);
if (col != rowValue.size() - 1) {
stringBuffer.append("\t");
}
}
if (row != table.size() - 1) {
stringBuffer.append("\n");
}
}
return stringBuffer.toString();
}
}

203
designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java

@ -0,0 +1,203 @@
package com.fr.design.data.datapane.preview;
import com.fr.design.base.clipboard.ClipboardHelper;
import com.fr.design.gui.itable.SortableJTable;
import com.fr.design.gui.itable.TableSorter;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.os.OperatingSystem;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class CopyableJTable extends SortableJTable {
//区域选中用到的定位数据
public int startRow = -1;
public int startCol = -1;
public int endRow = -1;
public int endCol = -1;
//单元格不连续多选用到的定位数据
java.util.List<Point> pointList = new ArrayList<>();
//shift键是否被按下
public boolean isShiftDown = false;
//control\command键是否被按下
public boolean isControlDown = false;
//是否可以复制
public boolean isCopy = true;
int ctrlKeyCode = 17;
int cKeyCode = 67;
int shiftKeyCode = 16;
int commandKeyCode = 157;
//选中单元格的背景色
Color selectBackGround = new Color(54, 133, 242, 63);
public CopyableJTable(TableSorter tableModel) {
super(tableModel);
initListener();
}
private void initListener() {
CopyableJTable self = this;
this.addMouseMotionListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseDragged(MouseEvent evt) {
int row = self.rowAtPoint(evt.getPoint());
int col = self.columnAtPoint(evt.getPoint());
if (self.updateEndPoint(row, col)) {
self.repaint();
}
}
});
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int row = self.rowAtPoint(e.getPoint());
int col = self.columnAtPoint(e.getPoint());
if (!self.isControlDown) {
self.clearPoint();
}
if (self.isShiftDown) {
self.clearPoint();
} else {
self.updateStartPoint(row, col);
}
self.addPoint(row, col);
self.updateEndPoint(row, col);
self.repaint();
}
});
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (isControlKey(e)) {
isControlDown = true;
} else if (e.getKeyCode() == shiftKeyCode) {
isShiftDown = true;
} else if (e.getKeyCode() == cKeyCode) {
if (isControlDown && isCopy) {
self.copy();
isCopy = false;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
if (isControlKey(e)) {
isControlDown = false;
isCopy = true;
} else if (e.getKeyCode() == shiftKeyCode) {
isShiftDown = false;
}
}
private boolean isControlKey(KeyEvent e) {
if (e.getKeyCode() == ctrlKeyCode) {
return true;
}
if (e.getKeyCode() == commandKeyCode && OperatingSystem.isMacos()) {
return true;
}
return false;
}
});
}
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
if (isChoose(row, column)) {
comp.setBackground(selectBackGround);
} else {
comp.setBackground(this.getBackground());
}
return comp;
}
private boolean updateEndPoint(int row, int col) {
if (endRow != row || endCol != col) {
endRow = row;
endCol = col;
return true;
}
return false;
}
private boolean updateStartPoint(int row, int col) {
if (startRow != row || startCol != col) {
startRow = row;
startCol = col;
return true;
}
return false;
}
private void addPoint(int row, int col) {
pointList.add(new Point(row, col));
}
private void clearPoint() {
pointList = new ArrayList<>();
}
private void copy() {
FineLoggerFactory.getLogger().info("copy cell value");
java.util.List<java.util.List<Object>> table = new ArrayList<>();
if ((startRow != endRow || startCol != endCol) &&
Math.min(startRow, endRow) > -1 && Math.min(startCol, endCol) > -1) {
for (int i = Math.min(startRow, endRow); i <= Math.max(startRow, endRow); i++) {
table.add(new ArrayList<>());
for (int j = Math.min(startCol, endCol); j <= Math.max(startCol, endCol); j++) {
Object text = this.getValueAt(i, j);
table.get(i - Math.min(startRow, endRow)).add(text);
}
}
} else if (pointList.size() > 0) {
Collections.sort(pointList, Comparator.comparing(Point::getX).thenComparing(Point::getY));
int startRow = pointList.get(0).x;
int currentRow = startRow;
table.add(new ArrayList<>());
for (Point point : pointList) {
while (currentRow < point.x) {
table.add(new ArrayList<>());
currentRow++;
}
Object text = this.getValueAt(point.x, point.y);
table.get(currentRow - startRow).add(text);
}
}
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable tText = new StringSelection(ClipboardHelper.formatExcelString(table));
clip.setContents(tText, null);
}
private boolean isChoose(int row, int col) {
if (row >= Math.min(startRow, endRow) && row <= Math.max(startRow, endRow)) {
if (col >= Math.min(startCol, endCol) && col <= Math.max(startCol, endCol)) {
return true;
}
}
for (Point point : pointList) {
if (point.x == row && point.y == col) {
return true;
}
}
return false;
}
}

3
designer-base/src/main/java/com/fr/design/data/datapane/preview/PreviewTablePane.java

@ -26,7 +26,6 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.function.TIME;
import com.fr.general.FRFont;
import com.fr.log.FineLoggerFactory;
@ -162,7 +161,7 @@ public class PreviewTablePane extends BasicPane {
}
});
preveiwTable = new SortableJTable(new TableSorter());
preveiwTable = new CopyableJTable(new TableSorter());
preveiwTable.setRowSelectionAllowed(false);
preveiwTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

203
designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java

@ -3,6 +3,7 @@
*/
package com.fr.design.cell.clipboard;
import com.fr.design.base.clipboard.ClipboardHelper;
import com.fr.grid.selection.CellSelection;
import com.fr.log.FineLoggerFactory;
import com.fr.report.cell.CellElement;
@ -12,8 +13,10 @@ import com.fr.report.elementcase.TemplateElementCase;
import com.fr.stable.StringUtils;
import com.fr.stable.unit.FU;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* The clip of CellElement.
@ -21,16 +24,16 @@ import java.util.Iterator;
public class CellElementsClip implements Cloneable, java.io.Serializable {
private int columnSpan = 0;
private int rowSpan = 0;
private FU[] columnWidth;
private FU[] rowHeight;
private FU[] columnWidth;
private FU[] rowHeight;
private TemplateCellElement[] clips;
public CellElementsClip(int columnSpan, int rowSpan, FU[] columnWidth , FU[] rowHeight, TemplateCellElement[] clips) {
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
this.columnWidth = columnWidth ;
this.rowHeight = rowHeight;
this.clips = clips;
public CellElementsClip(int columnSpan, int rowSpan, FU[] columnWidth, FU[] rowHeight, TemplateCellElement[] clips) {
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
this.columnWidth = columnWidth;
this.rowHeight = rowHeight;
this.clips = clips;
}
public CellElementsClip(int columnSpan, int rowSpan, TemplateCellElement[] clips) {
@ -39,122 +42,116 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
this.clips = clips;
}
public int getColumnSpan() {
return columnSpan;
}
public int getColumnSpan() {
return columnSpan;
}
public void setColumnSpan(int columnSpan) {
this.columnSpan = columnSpan;
}
public void setColumnSpan(int columnSpan) {
this.columnSpan = columnSpan;
}
public int getRowSpan() {
return rowSpan;
}
public int getRowSpan() {
return rowSpan;
}
public void setRowSpan(int rowSpan) {
this.rowSpan = rowSpan;
}
public void setRowSpan(int rowSpan) {
this.rowSpan = rowSpan;
}
public FU[] getColumnWidth() {
return columnWidth;
}
public FU[] getColumnWidth() {
return columnWidth;
}
public void setColumnWidth(FU[] columnWidth) {
this.columnWidth = columnWidth;
}
public void setColumnWidth(FU[] columnWidth) {
this.columnWidth = columnWidth;
}
public FU[] getRowHeight() {
return rowHeight;
}
public FU[] getRowHeight() {
return rowHeight;
}
public void setRowHeight(FU[] rowHeight) {
this.rowHeight = rowHeight;
}
public void setRowHeight(FU[] rowHeight) {
this.rowHeight = rowHeight;
}
public TemplateCellElement[] getClips() {
return clips;
}
public TemplateCellElement[] getClips() {
return clips;
}
public void setClips(TemplateCellElement[] clips) {
this.clips = clips;
}
public void setClips(TemplateCellElement[] clips) {
this.clips = clips;
}
public String compateExcelPaste() {
Arrays.sort(this.clips, CellElementComparator.getRowFirstComparator());
public String compateExcelPaste() {
Arrays.sort(this.clips, CellElementComparator.getRowFirstComparator());
// 排序
StringBuffer sbuf = new StringBuffer();
// 排序
int currentRow = -1;
for (int i = 0; i < clips.length; i++) {
CellElement cellElement = clips[i];
if (currentRow == -1) {// 初始化当前行.
currentRow = cellElement.getRow();
}
List<List<Object>> table = new ArrayList<>();
int startRow = -1;
int currentRow = -1;
for (int i = 0; i < clips.length; i++) {
CellElement cellElement = clips[i];
if (currentRow == -1) {// 初始化当前行.
currentRow = cellElement.getRow();
startRow = currentRow;
table.add(new ArrayList<>());
}
if (currentRow < cellElement.getRow()) {
for (int r = currentRow; r < cellElement.getRow(); r++) {
sbuf.append('\n');
}
currentRow = cellElement.getRow();
}
while (currentRow < cellElement.getRow()) {
table.add(new ArrayList<>());
currentRow++;
}
// 添加分隔符号.
if (sbuf.length() > 0 && sbuf.charAt(sbuf.length() - 1) != '\n') {
sbuf.append('\t');
}
//REPORT-5134:会复制出null
if (cellElement.getValue() == null) {
sbuf.append(StringUtils.EMPTY);
} else {
sbuf.append(cellElement.getValue());
}
}
Object cellValue = cellElement.getValue() == null ? StringUtils.EMPTY : cellElement.getValue();
table.get(currentRow - startRow).add(cellValue);
}
return sbuf.toString();
return ClipboardHelper.formatExcelString(table);
}
public CellSelection pasteAt(TemplateElementCase ec, int column, int row) {
Iterator cells = ec.intersect(column, row, columnSpan, rowSpan);
while (cells.hasNext()) {
TemplateCellElement cellElement = (TemplateCellElement)cells.next();
ec.removeCellElement(cellElement);
}
for (int i = 0; i < clips.length; i++) {
TemplateCellElement cellElement;
try {
cellElement = (TemplateCellElement) clips[i].clone();
} catch (CloneNotSupportedException e) {
Iterator cells = ec.intersect(column, row, columnSpan, rowSpan);
while (cells.hasNext()) {
TemplateCellElement cellElement = (TemplateCellElement) cells.next();
ec.removeCellElement(cellElement);
}
for (int i = 0; i < clips.length; i++) {
TemplateCellElement cellElement;
try {
cellElement = (TemplateCellElement) clips[i].clone();
} catch (CloneNotSupportedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return null;
}
// peter:因为前面已经将这个位置的元素删除了,所以不需要override了.
ec.addCellElement((TemplateCellElement) cellElement.deriveCellElement(
column + cellElement.getColumn(), row + cellElement.getRow()
), false);
}
//设置单元格的宽高
if(this.columnWidth != null && this.rowHeight != null){
return null;
}
// peter:因为前面已经将这个位置的元素删除了,所以不需要override了.
ec.addCellElement((TemplateCellElement) cellElement.deriveCellElement(
column + cellElement.getColumn(), row + cellElement.getRow()
), false);
}
//设置单元格的宽高
if (this.columnWidth != null && this.rowHeight != null) {
pasteWidthAndHeight(ec, column, row, columnSpan, rowSpan);
}
return new CellSelection(column, row, columnSpan, rowSpan);
return new CellSelection(column, row, columnSpan, rowSpan);
}
public void pasteWidthAndHeight(TemplateElementCase ec, int column, int row, int columnSpan, int rowSpan){
for(int i = 0; i < columnSpan; i++){
ec.setColumnWidth(column + i, columnWidth[i]);
}
for(int j = 0; j < rowSpan; j++){
ec.setRowHeight(row + j, rowHeight[j]);
}
}
public void pasteWidthAndHeight(TemplateElementCase ec, int column, int row, int columnSpan, int rowSpan) {
for (int i = 0; i < columnSpan; i++) {
ec.setColumnWidth(column + i, columnWidth[i]);
}
for (int j = 0; j < rowSpan; j++) {
ec.setRowHeight(row + j, rowHeight[j]);
}
}
public void pasteAtRegion(TemplateElementCase ec,
int startColumn, int startRow,
int column, int row,
int columnSpan, int rowSpan) {
int startColumn, int startRow,
int column, int row,
int columnSpan, int rowSpan) {
for (int i = 0; i < clips.length; i++) {
TemplateCellElement cellElement = clips[i];
@ -173,14 +170,14 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
* Clone.
*/
@Override
public Object clone() throws CloneNotSupportedException {
public Object clone() throws CloneNotSupportedException {
CellElementsClip cloned = (CellElementsClip) super.clone();
if (this.clips != null) {
cloned.clips = new TemplateCellElement[this.clips.length];
for (int i = 0; i < this.clips.length; i++) {
cloned.clips[i] = (TemplateCellElement)this.clips[i].clone();
}
cloned.clips = new TemplateCellElement[this.clips.length];
for (int i = 0; i < this.clips.length; i++) {
cloned.clips[i] = (TemplateCellElement) this.clips[i].clone();
}
}
return cloned;

Loading…
Cancel
Save