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

1439 lines
47 KiB

/*
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
*/
package com.fr.grid;
import com.fr.base.DynamicUnitList;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.cell.editor.*;
import com.fr.design.constants.UIConstants;
import com.fr.design.fun.GridUIProcessor;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.grid.event.CellEditorEvent;
import com.fr.grid.event.CellEditorListener;
import com.fr.grid.event.FloatEditorEvent;
import com.fr.grid.event.FloatEditorListener;
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.DefaultTemplateCellElement;
import com.fr.report.cell.FloatElement;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.cell.cellattr.CellGUIAttr;
import com.fr.report.cell.cellattr.CellImage;
import com.fr.report.cell.cellattr.core.RichText;
import com.fr.report.elementcase.ElementCase;
import com.fr.report.elementcase.TemplateElementCase;
import com.fr.stable.StringUtils;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Hashtable;
import java.util.Iterator;
/**
* Grid used to paint and edit grid.
*
* @editor zhou 2012-3-22下午1:58:12
*/
// TODO ALEX_SEP 能不能把CellSelection作为Grid的属性,以此来分开CellSelection & FloatSelection
public class Grid extends BaseGridComponent {
/**
* If editing, the <code>Component</code> that is handling the editing.
*/
private static final int VERTICAL_EXTENT_INITIAL_VALUE = 50;
private static final int HORIZONTAL_EXTENT_INITIAL_VALUE = 40;
transient protected Component editorComponent;
transient private Point2D editorComponentLoc;
transient private TemplateCellElement editingCellElement;
private boolean showGridLine = true;
private Color gridLineColor = UIConstants.RULER_LINE_COLOR; // line color.
private boolean isShowPaginateLine = true;
private Color paginationLineColor = Color.RED; // line color of paper
private boolean isShowVerticalFrozenLine = true;
private Color verticalFrozenLineColor = Color.black;
private boolean isShowHorizontalFrozenLine = true;
private Color horizontalFrozenLineColor = Color.black;
private Color selectedBackground = UIConstants.SELECTED_BACKGROUND;
private Color selectedBorderLineColor = UIConstants.SELECTED_BORDER_LINE_COLOR;
private boolean editable = true; // 整体的总开关,控制格子是否可以编辑.
private FloatElement drawingFloatElement = null;
private int dragType = GridUtils.DRAG_NONE;// Drag的标志.
// peter:Drag格子的时候,需要显示的边框,当为null的时候不画.
private Rectangle dragRectangle = null;
// ToolTip
private Point tooltipLocation;
/**
* The object that overwrites the screen real estate occupied by the current
* cell and allows the user to change its contents.
*/
transient private CellEditor cellEditor;
/**
* The object that overwrites the screen real estate occupied by the current
* float and allows the user to change its contents.
*/
transient private FloatEditor floatEditor;
/**
* Identifies the column of the cell being edited.
*/
transient private int editingColumn;
/**
* Identifies the row of the cell being edited.
*/
transient private int editingRow;
// A table of objects that display and edit the contents of a cell.
transient private Hashtable<Class, CellEditor> defaultCellEditorsByClass;
// A table of objects that display and edit the contents of a float.
transient private Hashtable<Class, FloatEditor> defaultFloatEditorsByClass;
// Vertical and Horizontal value.
private int verticalValue = 0;
private int verticalExtent = VERTICAL_EXTENT_INITIAL_VALUE;
private int horizontalValue = 0;
private int horizontalExtent = HORIZONTAL_EXTENT_INITIAL_VALUE;// marks:这个值从原来的10换成20,因为现在电脑都是宽屏,10已经没有办法满足需求!
// denny: verticalBeginValue and horizantalBeginValue
private int verticalBeginValue = 0;
private int horizontalBeginValue = 0;
private int resolution;
// 判断SmartJTablePane是否显示,做为动态虚线标识符
private boolean notShowingTableSelectPane = true;
private GridMouseAdapter gridMouseAdapter;
public Grid(int resolution) {
this.resolution = resolution;
// 能触发processEvent,不管是否给component增加listener
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
GridKeyAction.initGridInputActionMap(this);
gridMouseAdapter = new GridMouseAdapter(this);
this.addMouseListener(gridMouseAdapter);
this.addMouseMotionListener(gridMouseAdapter);
this.addMouseWheelListener(gridMouseAdapter);
this.addKeyListener(new GridKeyListener(this));
// JDK1.4
this.setFocusTraversalKeysEnabled(false);
this.setOpaque(false);
this.updateUI();
}
public void setResolution(int resolution) {
this.resolution = resolution;
}
public int getResolution() {
return this.resolution;
}
/**
* 应用界面设置
*
* @date 2014-12-21-下午6:32:43
*/
public void updateUI() {
GridUIProcessor localGridUIProcessor = ExtraDesignClassManager.getInstance().getSingle(GridUIProcessor.MARK_STRING, new DefaultGridUIProcessor());
ComponentUI localComponentUI = localGridUIProcessor.appearanceForGrid(this.resolution);
setUI(localComponentUI);
}
/**
* 是否显示格子线
*
* @return 是否显示格子线
* @date 2014-12-21-下午6:32:13
*/
public boolean isShowGridLine() {
return showGridLine;
}
/**
* Sets whether to show grid line.
*
* @param isShowGridLine whether to show grid line.
*/
public void setShowGridLine(boolean isShowGridLine) {
this.showGridLine = isShowGridLine;
this.getElementCasePane().repaint();
}
public GridMouseAdapter getGridMouseAdapter() {
return this.gridMouseAdapter;
}
/**
* Gets grid line color.
*
* @return grid line color.
*/
public Color getGridLineColor() {
return this.gridLineColor;
}
/**
* Sets grid line color.
*
* @param gridLineColor the new color of line.
*/
public void setGridLineColor(Color gridLineColor) {
Color old = this.gridLineColor;
this.gridLineColor = gridLineColor;
this.firePropertyChange("girdLineColor", old, this.gridLineColor);
this.getElementCasePane().repaint();
}
/**
* 是否显示分页线
*
* @return 是否显示分页线
* @date 2014-12-21-下午6:31:45
*/
public boolean isShowPaginateLine() {
return isShowPaginateLine;
}
/**
* Sets to show pagination line.
*/
public void setShowPaginateLine(boolean showPaginateLine) {
this.isShowPaginateLine = showPaginateLine;
this.getElementCasePane().repaint();
}
/**
* Gets pagination line color.
*/
public Color getPaginationLineColor() {
return this.paginationLineColor;
}
/**
* Sets pagination line color.
*
* @param paginationLineColor the new color of pagination line.
*/
public void setPaginationLineColor(Color paginationLineColor) {
Color old = this.paginationLineColor;
this.paginationLineColor = paginationLineColor;
this.firePropertyChange("paginationLineColor", old, this.paginationLineColor);
this.getElementCasePane().repaint();
}
/**
* 是否显示垂直冻结线
*
* @return 是否显示垂直冻结线
* @date 2014-12-21-下午6:29:35
*/
public boolean isShowVerticalFrozenLine() {
return isShowVerticalFrozenLine;
}
/**
* Sets to show vertical frozen line.
*/
public void setShowVerticalFrozenLine(boolean showVerticalFrozenLine) {
this.isShowVerticalFrozenLine = showVerticalFrozenLine;
this.getElementCasePane().repaint();
}
/**
* Gets vertical frozen line color.
*/
public Color getVerticalFrozenLineColor() {
return verticalFrozenLineColor;
}
/**
* Sets vertical frozen line color.
*
* @param verticalFrozenLineColor the new color of vertical frozen line.
*/
public void setVerticalFrozenLineColor(Color verticalFrozenLineColor) {
Color old = this.verticalFrozenLineColor;
this.verticalFrozenLineColor = verticalFrozenLineColor;
this.firePropertyChange("verticalFrozenLineColor", old, this.verticalFrozenLineColor);
this.getElementCasePane().repaint();
}
/**
* 是否显示水平冻结线
*
* @return 是否显示水平冻结线
* @date 2014-12-21-下午6:29:35
*/
public boolean isShowHorizontalFrozenLine() {
return isShowHorizontalFrozenLine;
}
/**
* Sets to show horizontal frozen line.
*/
public void setShowHorizontalFrozenLine(boolean showHorizontalFrozenLine) {
this.isShowHorizontalFrozenLine = showHorizontalFrozenLine;
this.getElementCasePane().repaint();
}
/**
* Gets horizontal frozen line color.
*/
public Color getHorizontalFrozenLineColor() {
return horizontalFrozenLineColor;
}
/**
* Sets horizontal frozen line color.
*
* @param horizontalFrozenLineColor the new color of horizontal frozen line.
*/
public void setHorizontalFrozenLineColor(Color horizontalFrozenLineColor) {
Color old = this.horizontalFrozenLineColor;
this.horizontalFrozenLineColor = horizontalFrozenLineColor;
this.firePropertyChange("horizontalFrozenLineColor", old, this.horizontalFrozenLineColor);
this.getElementCasePane().repaint();
}
/**
* Gets the selected background.
*/
public Color getSelectedBackground() {
return this.selectedBackground;
}
/**
* Sets the selected background.
*
* @param selectedBackground the new selected background.
*/
public void setSelectedBackground(Color selectedBackground) {
Color old = this.selectedBackground;
this.selectedBackground = selectedBackground;
this.firePropertyChange("selectedBackground", old, this.selectedBackground);
this.getElementCasePane().repaint();
}
/**
* Gets the selected border line color.
*/
public Color getSelectedBorderLineColor() {
return selectedBorderLineColor;
}
/**
* Sets the selected border line color.
*
* @param selectedBorderLineColor the new color of selected border line.
*/
public void setSelectedBorderLineColor(Color selectedBorderLineColor) {
Color old = this.selectedBorderLineColor;
this.selectedBorderLineColor = selectedBorderLineColor;
this.firePropertyChange("selectedBorderLineColor", old, this.selectedBorderLineColor);
this.getElementCasePane().repaint();
}
/**
* 组件是否可以被编辑
*
* @return 组件是否可以被编辑
* @date 2014-12-21-下午6:29:09
*/
public boolean isEditable() {
return editable;
}
/**
* Sets whether to editable.
*/
public void setEditable(boolean editable) {
this.editable = editable;
}
/**
* @return
*/
public FloatElement getDrawingFloatElement() {
return drawingFloatElement;
}
/**
* @param drawingFloatElement
*/
public void setDrawingFloatElement(FloatElement drawingFloatElement) {
this.drawingFloatElement = drawingFloatElement;
}
/**
* @return
*/
public int getVerticalValue() {
return verticalValue;
}
/**
* @param verticalValue
*/
public void setVerticalValue(int verticalValue) {
this.verticalValue = verticalValue;
}
/**
* @return
*/
public int getVerticalExtent() {
return verticalExtent;
}
/**
* @param verticalExtent
*/
public void setVerticalExtent(int verticalExtent) {
this.verticalExtent = verticalExtent;
}
/**
* // denny: add the get and set method of verticalBeginValue
*
* @return
*/
public int getVerticalBeginValue() {
return verticalBeginValue;
}
/**
* @param verticalBeginValue
*/
public void setVerticalBeinValue(int verticalBeginValue) {
this.verticalBeginValue = verticalBeginValue;
}
/**
* @return
*/
public int getHorizontalExtent() {
return horizontalExtent;
}
/**
* @param horizontalExtent
*/
public void setHorizontalExtent(int horizontalExtent) {
this.horizontalExtent = horizontalExtent;
}
/**
* @return
*/
public int getHorizontalValue() {
return horizontalValue;
}
/**
* @param horizontalValue
*/
public void setHorizontalValue(int horizontalValue) {
this.horizontalValue = horizontalValue;
}
/**
* denny: add the get and set method of horizontalBeginValue
*
* @return
*/
public int getHorizontalBeginValue() {
return this.horizontalBeginValue;
}
/**
* @param horizontalBeginValue
*/
public void setHorizontalBeginValue(int horizontalBeginValue) {
this.horizontalBeginValue = horizontalBeginValue;
}
// /////////////editor begin
/**
* 是否处于编辑状态
*
* @return 是否处于编辑状态
* @date 2014-12-21-下午6:28:45
*/
public boolean isEditing() {
return this.editorComponent != null;
}
/**
* 当前编辑对象是否为单元格
*
* @return 当前编辑对象是否为单元格
* @date 2014-12-21-下午6:28:18
*/
public boolean isCellEditing() {
return this.isEditing() && cellEditor != null && notShowingTableSelectPane;
}
/**
* @param f
*/
public void setNotShowingTableSelectPane(boolean f) {
this.notShowingTableSelectPane = f;
}
/**
* 是否处于智能选择单元格阶段
*
* @return 是否处于智能选择单元格阶段
* @date 2014-12-21-下午6:27:36
*/
public boolean IsNotShowingTableSelectPane() {
return this.notShowingTableSelectPane;
}
/**
* 当前是否在编辑悬浮元素
*
* @return 是否在编辑悬浮元素
* @date 2014-12-21-下午6:26:46
*/
public boolean isFloatEditing() {
return this.isEditing() && floatEditor != null;
}
/**
* Returns an appropriate editor for the cell specified by
* <code>column</code> and <code>row</code>.
*
* @param column the column of the cell to edit, where 0 is the first column;
* @param row the row of the cell to edit, where 0 is the first row
* @return the editor for this cell; if <code>null</code> return the default
* editor for this type of cell
* @see com.fr.design.cell.editor.CellEditor
*/
public CellEditor getCellEditor(int column, int row) {
ElementCasePane reportPane = this.getElementCasePane();
ElementCase report = reportPane.getEditingElementCase();
CellElement cellElement = report.getCellElement(column, row);
// 获得对象.
Class objClass = Object.class;// 默认对象是Object.
if (cellElement != null && cellElement.getValue() != null) {
objClass = cellElement.getValue().getClass();
}
return this.getDefaultCellEditor(objClass);
}
/**
* Gets the component that is handling the editing session. If nothing is
* being edited, returns null.
*
* @return Component handling editing session
*/
public Component getEditorComponent() {
return this.editorComponent;
}
/**
* Gets the index of the column that contains the cell currently being
* edited. If nothing is being edited, returns -1.
*
* @return the index of the column that contains the cell currently being
* edited; returns -1 if nothing being edited
*/
public int getEditingColumn() {
return editingColumn;
}
/**
* Sets the <code>editingColumn</code> variable.
*
* @param editingColumn the column of the cell to be edited
*/
public void setEditingColumn(int editingColumn) {
this.editingColumn = editingColumn;
}
/**
* Gets the index of the row that contains the cell currently being edited.
* If nothing is being edited, returns -1.
*
* @return the index of the row that contains the cell currently being
* edited; returns -1 if nothing being edited
*/
public int getEditingRow() {
return editingRow;
}
/**
* Sets the <code>editingRow</code> variable.
*
* @param editingColumn the row of the cell to be edited
*/
public void setEditingRow(int editingColumn) {
this.editingRow = editingColumn;
}
/**
* Gets the cell editor.
*
* @return the <code>CellEditor</code> that does the editing
*/
public CellEditor getCellEditor() {
return cellEditor;
}
/**
* Gets the float editor.
*
* @return the <code>FloatEditor</code> that does the editing
*/
public FloatEditor getFloatEditor() {
return this.floatEditor;
}
/**
* Sets the <code>cellEditor</code> variable.
*
* @param anEditor the CellEditor that does the editing
*/
public void setCellEditor(CellEditor anEditor) {
CellEditor old = this.cellEditor;
this.cellEditor = anEditor;
firePropertyChange("CellEditor", old, this.cellEditor);
}
/**
* Sets the <code>FloatEditor</code> variable.
*
* @param anEditor the FloatEditor that does the editing
*/
public void setFloatEditor(FloatEditor anEditor) {
FloatEditor old = this.floatEditor;
this.floatEditor = anEditor;
firePropertyChange("FloatEditor", old, this.floatEditor);
}
/**
* Gets the cell editor to be edit Object class.
*
* @return the default cell editor to be used for Object Class
* @see #setDefaultCellEditor
* @see com.fr.report.cell.CellElement#getValue
*/
public CellEditor getDefaultCellEditor() {
return this.getDefaultCellEditor(Object.class);
}
/**
* Gets the float editor to be edit Object class.
*
* @return the default float editor to be used for Object Class
* @see #setDefaultFloatEditor
* @see com.fr.report.cell.FloatElement#getValue
*/
public FloatEditor getDefaultFloatEditor() {
return this.getDefaultFloatEditor(Object.class);
}
/**
* Sets the cell editor to be edit the Object class.
*
* @param editor default cell editor to be used for Object Class
* @see #getDefaultCellEditor
*/
public void setDefaultCellEditor(CellEditor editor) {
this.setDefaultCellEditor(Object.class, editor);
}
/**
* Sets the float editor to be edit the Object class.
*
* @param editor default float editor to be used for Object Class
* @see #getDefaultFloatEditor
*/
public void setDefaultFloatEditor(FloatEditor editor) {
this.setDefaultFloatEditor(Object.class, editor);
}
/**
* Gets the editor to be edit the class. The <code>Grid</code> installs
* entries for <code>Object</code>, <code>Number</code>,
* <code>Boolean</code>,and all values that supported by CellElement.
*
* @param objectClass return the default cell editor for this Class
* @return the default cell editor to be used for this Class
* @see #setDefaultCellEditor
* @see com.fr.report.cell.CellElement#getValue
*/
public CellEditor getDefaultCellEditor(Class objectClass) {
if (objectClass == null) {
objectClass = Object.class;
}
CellEditor editor = this.prepareDefaultCellEditorsByClass().get(objectClass);
if (editor != null) {
return editor;
} else {
return getDefaultCellEditor(objectClass.getSuperclass());
}
}
/**
* Gets the float editor to be edit the class. The <code>Grid</code>
* installs entries for <code>Object</code>, <code>Number</code>,
* <code>Boolean</code>,and all values that supported by FloatElement.
*
* @param objectClass return the default float editor for this Class
* @return the default cell editor to be used for this Class
* @see #setDefaultFloatEditor
* @see com.fr.report.cell.FloatElement#getValue
*/
public FloatEditor getDefaultFloatEditor(Class objectClass) {
if (objectClass == null) {
objectClass = Object.class;
}
FloatEditor editor = this.prepareDefaultFloatEditorsByClass().get(objectClass);
if (editor != null) {
return editor;
} else {
return getDefaultFloatEditor(objectClass.getSuperclass());
}
}
/**
* Sets the editor to be edit the class. The <code>Grid</code> installs
* entries for <code>Object</code>, <code>Number</code>,
* <code>Boolean</code>,and all values that supported by CellElement.
*
* @param objectClass set the default cell editor for this Class
* @param editor default cell editor to be used for this Class
* @see #getDefaultCellEditor
* @see com.fr.report.cell.CellElement#getValue
*/
public void setDefaultCellEditor(Class objectClass, CellEditor editor) {
if (editor != null) {
this.prepareDefaultCellEditorsByClass().put(objectClass, editor);
} else {
this.prepareDefaultCellEditorsByClass().remove(objectClass);
}
}
/**
* Sets the float editor to be edit the class. The <code>Grid</code>
* installs entries for <code>Object</code>, <code>Number</code>,
* <code>Boolean</code>,and all values that supported by CellElement.
*
* @param objectClass set the default float editor for this Class
* @param floatEditor default float editor to be used for this Class
* @see #getDefaultFloatEditor
* @see com.fr.report.cell.FloatElement#getValue
*/
public void setDefaultFloatEditor(Class objectClass, FloatEditor floatEditor) {
if (floatEditor != null) {
this.prepareDefaultFloatEditorsByClass().put(objectClass, floatEditor);
} else {
this.prepareDefaultFloatEditorsByClass().remove(objectClass);
}
}
/**
* 开始单元格编辑
*
* @date 2014-12-21-下午6:25:17
*/
public void startEditing() {
this.startEditing(false);
}
/**
* 开始单元格编辑
*
* @param byKeyEvent 是否为键盘触发
* @date 2014-12-21-下午6:25:17
*/
protected void startEditing(boolean byKeyEvent) {
ElementCasePane reportPane = this.getElementCasePane();
ElementCase report = reportPane.getEditingElementCase();
Selection s = reportPane.getSelection();
if (s instanceof FloatSelection) {
FloatElement selectedFloatElement = report.getFloatElement(((FloatSelection) s).getSelectedFloatName());
this.stopEditing();// 需要先停止.
Object value = selectedFloatElement.getValue();
if (value == null) {
this.floatEditor = this.getDefaultFloatEditor();
} else {
this.floatEditor = this.getDefaultFloatEditor(value.getClass());
}
if (this.floatEditor == null) {
// peter:清空editorComponent.
this.editorComponent = null;
return;
}
this.editorComponent = this.floatEditor.getFloatEditorComponent(this, selectedFloatElement, resolution);
if (this.editorComponent == null) {
removeEditor();
return;
}
floatEditor.addFloatEditorListener(innerFloatEditorListener);
this.setFloatEditor(floatEditor);
if (this.editorComponent instanceof Window) {
this.editorComponent.setVisible(true);
} else {
this.ajustEditorComponentBounds();
this.add(this.editorComponent);
this.validate();
this.editorComponent.requestFocus();
this.repaint(10);
}
} else {// james:
// Edit CellElement.
CellSelection cs = (CellSelection) s;
startCellEditingAt_DEC(cs.getColumn(), cs.getRow(), null, byKeyEvent);
}
}
/**
* 开始单元格编辑
*
* @param column 列
* @param row 行
* @param cellTypeClass 单元格类型
* @param byKeyEvent 是否为键盘触发
* @return 编辑是否成功
* @date 2014-12-21-下午6:25:17
*/
public boolean startCellEditingAt_DEC(int column, int row, Class cellTypeClass, boolean byKeyEvent) {
if (this.isEditing()) {
this.stopEditing();// 需要先停止正在进行的编辑.
}
if (!this.isEditable()) {// 判断总开关,是否可以编辑.
return false;
}
if (row < 0 || column < 0) {
return false;
}
ElementCasePane reportPane = this.getElementCasePane();
TemplateElementCase report = reportPane.getEditingElementCase();
editingCellElement = report.getTemplateCellElement(column, row);
this.cellEditor = cellTypeClass == null ? this.getCellEditor(column, row) : this.getDefaultCellEditor(cellTypeClass);
if (this.cellEditor == null) {
this.editorComponent = null;
return false;
}
// 必须保证editingCellElement不是null。
if (editingCellElement == null) {
editingCellElement = new DefaultTemplateCellElement(column, row);
}
editorComponent = getCellEditingComp();
if (editorComponent == null) {
return false;
}
this.setEditingColumn(column);
this.setEditingRow(row);
if (editorComponent instanceof Window) {
editorComponent.setVisible(true);
} else {
// 如果是从KeyEvent启动的话,如果是文本或者数字,需要清空内容.
if (byKeyEvent && editorComponent instanceof UITextField) {
((UITextField) editorComponent).setText(StringUtils.EMPTY);
}
startInnerEditing(column, row);
}
return false;
}
private Component getCellEditingComp() {
// marks:这个地方获得editor
Component eComp = this.cellEditor.getCellEditorComponent(this, editingCellElement, resolution);
if (eComp == null) {
removeEditor();
} else {
this.editorComponentLoc = this.cellEditor.getLocationOnCellElement();
cellEditor.addCellEditorListener(innerCellEditorListener);
this.setCellEditor(cellEditor);
}
return eComp;
}
/**
* 就在单元格里面编辑
*/
private void startInnerEditing(int column, int row) {
this.editingRow = this.editingCellElement.getRow();
this.editingColumn = this.editingCellElement.getColumn();
this.ajustEditorComponentBounds();
this.add(this.editorComponent);
this.getElementCasePane().ensureColumnRowVisible(column, row);
this.validate();
// 需要重新绘制界面
this.repaint(10);
this.editorComponent.requestFocus();
}
/**
* 停止编辑状态
*
* @date 2014-12-21-下午6:24:54
*/
public void stopEditing() {
// 首先判断是哪种类型的编辑.
if (this.isCellEditing()) {
this.stopCellEditingInner(true);
}
if (this.isFloatEditing()) {
this.stopFloatEditingInner(true);
}
}
/**
* Stop editing. 当编辑器因为点击按钮失去焦点后,不需要Request Focus.
*/
private void stopFloatEditingInner(boolean isRequestFocus) {
if (!this.isFloatEditing()) {
return;
}
if (floatEditor == null) {
if (this.editorComponent != null) {
this.remove(this.editorComponent);
}
return;
}
Object newValue = null;
try {
newValue = floatEditor.getFloatEditorValue();
} catch (Exception exp) { // 捕捉错误信息.
}
if (newValue == null) {// If return null, do nothing.
removeEditor();
return;
}
ElementCasePane reportPane = this.getElementCasePane();
Selection selection = reportPane.getSelection();
if (selection instanceof FloatSelection) {// kunsnat: 类型判断, 经常在删除悬浮元素时 遇到停止编辑错误.
FloatSelection fs = (FloatSelection) reportPane.getSelection();
FloatElement selectedFloatElement = reportPane.getEditingElementCase().getFloatElement(fs.getSelectedFloatName());
Object oldValue = selectedFloatElement.getValue();
if (!ComparatorUtils.equals_exactly(oldValue, newValue)) {
if (newValue instanceof CellImage) {
CellImage cellImage = (CellImage) newValue;
newValue = cellImage.getImage();
if (cellImage.getStyle() != null) {
selectedFloatElement.setStyle(cellImage.getStyle());
}
}
selectedFloatElement.setValue(newValue);
reportPane.fireTargetModified();
//加这句话是为了在编辑完悬浮元素公式的时候,点击确定,右上角面板会立即刷新
reportPane.getCurrentEditor();
}
}
removeEditor();
if (isRequestFocus && !this.hasFocus()) {
this.requestFocus();
}
}
/**
* Stop editing. 当编辑器因为点击按钮失去焦点后,不需要Request Focus.
*/
private void stopCellEditingInner(boolean isRequestFocus) {
if ((!this.isCellEditing())) {
return;
}
if (cellEditor == null) {
if (this.editorComponent != null) {
this.remove(this.editorComponent);
}
return;
}
ElementCasePane reportPane = this.getElementCasePane();
TemplateElementCase tplEC = reportPane.getEditingElementCase();
Object newValue = null;
Object oldValue = null;
// CellAdapter
this.editingCellElement = tplEC.getTemplateCellElement(editingColumn, editingRow);
try {
newValue = cellEditor.getCellEditorValue();
} catch (Exception exp) { // 捕捉错误信息.
}
if (cellEditor instanceof TextCellEditor) {
oldValue = ((TextCellEditor) cellEditor).getOldValue();
}
if (isValueEmpty(newValue)) {
reportPane.clearContents();
if (cellEditor instanceof FormulaCellEditor || !isValueEmpty(oldValue)) {
reportPane.fireTargetModified();
}
removeEditor();
return;
}
// 必须保证editingCellElement不是null。
if (editingCellElement == null) {
editingCellElement = new DefaultTemplateCellElement(editingColumn, editingRow);
tplEC.addCellElement(editingCellElement);
}
if (setValue4EditingElement(newValue)) {
shrinkToFit(tplEC);
reportPane.fireTargetModified();
}
removeEditor();
if (isRequestFocus && !this.hasFocus()) {
this.requestFocus();
}
}
private boolean isValueEmpty(Object newValue) {
return (newValue == null || ComparatorUtils.equals(newValue, StringUtils.EMPTY));
}
/**
* @return editingCellElement 的字符串表示
*/
public String getEditingCellElement() {
return editingCellElement.toString();
}
/**
* 将新值赋给editingCellElement
*
* @param newValue
* @return true if the value changed
*/
private boolean setValue4EditingElement(Object newValue) {
if (newValue instanceof TemplateCellElement) {
TemplateCellElement cellElement = (TemplateCellElement) newValue;
editingCellElement.setValue(cellElement.getValue());
editingCellElement.setCellExpandAttr(cellElement.getCellExpandAttr());
return true;
} else if (newValue instanceof CellImage) {
CellImage cellImage = (CellImage) newValue;
newValue = cellImage.getImage();
boolean styleChange = false;
if (!ComparatorUtils.equals_exactly(cellImage.getStyle(), editingCellElement.getStyle())) {
editingCellElement.setStyle(cellImage.getStyle());
styleChange = true;
}
Object oldValue = this.editingCellElement.getValue();
boolean imageChange = false;
if (!ComparatorUtils.equals_exactly(oldValue, newValue)) {
editingCellElement.setValue(newValue);
imageChange = true;
}
if (styleChange || imageChange) {
return true;
}
} else {
if (newValue instanceof RichText) {
setShowAsHtml(this.editingCellElement);
}
Object oldValue = this.editingCellElement.getValue();
if (!ComparatorUtils.equals_exactly(oldValue, newValue)) {
editingCellElement.setValue(newValue);
return true;
}
}
return false;
}
private void setShowAsHtml(CellElement cellElement) {
CellGUIAttr guiAttr = cellElement.getCellGUIAttr();
if (guiAttr == null) {
guiAttr = new CellGUIAttr();
cellElement.setCellGUIAttr(guiAttr);
}
guiAttr.setShowAsHTML(true);
}
/**
* 当单元格里的内容过长时,自动调整单元格
*
* @param tplEC
*/
private void shrinkToFit(TemplateElementCase tplEC) {
if (editingCellElement == null) {
return;
}
Object editElementValue = editingCellElement.getValue();
if (valueNeedFit(editElementValue)) {
int mode = this.getElementCasePane().getReportSettings().getShrinkToFitMode();
GridUtils.shrinkToFit(mode, tplEC, editingCellElement);
}
}
//是否需要根据内容自动调整, 目前只有字符串, 数字, 富文本需要
private boolean valueNeedFit(Object value) {
if (value == null) {
return false;
}
return value instanceof String ||
value instanceof Number ||
value instanceof RichText;
}
/**
* 取消编辑状态
*
* @date 2014-12-21-下午6:24:34
*/
public void cancelEditing() {
if (this.isEditing()) {
removeEditor();
this.requestFocus();
}
}
/**
* 移除选中组件
*
* @date 2014-12-21-下午6:24:16
*/
public void removeEditor() {
if (this.isCellEditing()) {
this.removeCellEditor();
} else {
this.removeFloatEditor();
}
}
/**
* 移除单元格组件
*
* @date 2014-12-21-下午6:24:00
*/
public void removeCellEditor() {
CellEditor cellEditor = getCellEditor();
if (cellEditor == null) {
return;
}
if (this.editorComponent != null) {
if (this.editorComponent instanceof Window) {
editorComponent.setVisible(false);
((Window) editorComponent).dispose();
} else {
this.remove(this.editorComponent);
this.validate();
}
}
cellEditor.removeCellEditorListener(innerCellEditorListener);
setCellEditor(null);
setEditingColumn(-1);
setEditingRow(-1);
this.editorComponent = null;
this.editingCellElement = null;
this.getElementCasePane().repaint();
}
/**
* 移除悬浮元素组件
*
* @date 2014-12-21-下午6:23:38
*/
public void removeFloatEditor() {
FloatEditor floatEditor = getFloatEditor();
if (floatEditor != null) {
if (this.editorComponent != null) {
if (this.editorComponent instanceof Window) {
editorComponent.setVisible(false);
((Window) editorComponent).dispose();
} else {
this.remove(this.editorComponent);
this.validate();
}
}
floatEditor.removeFloatEditorListener(innerFloatEditorListener);
}
setFloatEditor(null);
this.editorComponent = null;
this.getElementCasePane().repaint();
}
/**
* 用这个方法来初始化defaultEditorsByClass, 是为了加快Grid对象的初始化速度.
* 当用户编辑的时候,才将那个CellEditor的初始化.
*/
private Hashtable<Class, CellEditor> prepareDefaultCellEditorsByClass() {
if (this.defaultCellEditorsByClass == null) {
this.defaultCellEditorsByClass = new Hashtable<Class, CellEditor>();
defaultCellEditorsByClass.put(Object.class, new GeneralCellEditor());
}
return this.defaultCellEditorsByClass;
}
/**
* 用这个方法来初始化defaultFloatEditorsByClass, 是为了加快Grid对象的初始化速度.
* 当用户编辑的时候,才将那个FloatEditor的初始化.
*/
private Hashtable<Class, FloatEditor> prepareDefaultFloatEditorsByClass() {
if (this.defaultFloatEditorsByClass == null) {
this.defaultFloatEditorsByClass = new Hashtable<Class, FloatEditor>();
defaultFloatEditorsByClass.put(Object.class, new GeneralFloatEditor());
}
return this.defaultFloatEditorsByClass;
}
// /////////////editor end
/**
* 鼠标点击事件
*
* @param evtX x坐标
* @param evtY y坐标
* @date 2014-12-21-下午6:22:56
*/
public void doMousePress(double evtX, double evtY) {
dispatchEvent(new MouseEvent(this, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), 0, (int) evtX, (int) evtY, 1, false));
}
/**
* 计算oldRectangle,因为CellElement的合并会变成多大的区域.
*
* @param report 当前格子报表
* @param oldRectangle 之前的选中区域
* @return 插入的区域
* @date 2014-12-21-下午6:22:21
*/
public Rectangle caculateIntersectsUnion(ElementCase report, Rectangle oldRectangle) {
Rectangle newRectangle = new Rectangle(oldRectangle);
Iterator cells = report.intersect(newRectangle.x, newRectangle.y, newRectangle.width, newRectangle.height);
while (cells.hasNext()) {
CellElement cellElement = (CellElement) cells.next();
Rectangle tmpCellElementRect = new Rectangle(cellElement.getColumn(), cellElement.getRow(), cellElement.getColumnSpan(), cellElement.getRowSpan());
if (newRectangle.intersects(tmpCellElementRect) && !newRectangle.contains(tmpCellElementRect)) {
newRectangle = newRectangle.union(tmpCellElementRect);
}
}
// 检查十分需要从新再循环一遍.
if (!GUICoreUtils.isTheSameRect(newRectangle, oldRectangle)) {
return this.caculateIntersectsUnion(report, newRectangle);
}
return newRectangle;
}
/**
* @param event
* @return
*/
public Point getToolTipLocation(MouseEvent event) {
if (StringUtils.isEmpty(this.getToolTipText())) {
return null;
}
if (tooltipLocation == null) {
tooltipLocation = new Point();
}
return this.tooltipLocation;
}
/**
* peter:重新调整editorComponent的宽度和高度,几乎是界面有变化就调整.
*/
public void ajustEditorComponentBounds() {
// 没有编辑器或者对于弹出的Window不需要调整Bound.
if (this.editorComponent == null || this.editorComponent instanceof Window) {
return;
}
ElementCasePane reportPane = this.getElementCasePane();
ElementCase report = reportPane.getEditingElementCase();
// four anchor values.
DynamicUnitList rowHeightList = ReportHelper.getRowHeightList(report);
DynamicUnitList columnWidthList = ReportHelper.getColumnWidthList(report);
// 调整X, Y, width, height
double x, y, width, height;
Selection s = reportPane.getSelection();
if (s instanceof FloatSelection) {
FloatElement selectedFloatElement = report.getFloatElement(((FloatSelection) s).getSelectedFloatName());
int h = reportPane.getHorizontalScrollBar().getValue();
int v = reportPane.getVerticalScrollBar().getValue();
x = selectedFloatElement.getLeftDistance().toPixD(this.resolution) + columnWidthList.getRangeValue(h, 0).toPixD(this.resolution);
y = selectedFloatElement.getTopDistance().toPixD(this.resolution) + rowHeightList.getRangeValue(v, 0).toPixD(this.resolution);
width = selectedFloatElement.getWidth().toPixD(this.resolution);
height = selectedFloatElement.getHeight().toPixD(this.resolution);
} else {
x = columnWidthList.getRangeValue(this.horizontalBeginValue, this.editingColumn).toPixD(this.resolution);
y = rowHeightList.getRangeValue(this.verticalBeginValue, this.editingRow).toPixD(this.resolution);
int columnSpan = this.editingCellElement != null ? this.editingCellElement.getColumnSpan() : 1;
int rowSpan = this.editingCellElement != null ? this.editingCellElement.getRowSpan() : 1;
width = columnWidthList.getRangeValue(this.editingColumn, this.editingColumn + columnSpan).toPixD(this.resolution) - 1;
height = rowHeightList.getRangeValue(this.editingRow, this.editingRow + rowSpan).toPixD(this.resolution) - 1;
}
applayRect(x, y, width, height);
}
private void applayRect(double x, double y, double width, double height) {
// peter:需要检查Loc来调整editorComponent的location.
if (this.editorComponentLoc == null) {
this.editorComponent.setLocation((int) (x + 1), (int) (y + 1));
} else {
this.editorComponent.setLocation((int) (x + this.editorComponentLoc.getX()), (int) (y + this.editorComponentLoc.getY()));
}
// 专门处理TextField, TextField的长度需要跟着文本的总长度来变化.
if (this.editorComponent instanceof UITextField) {
Dimension textPrefSize = this.editorComponent.getPreferredSize();
// peter:对于文本左右需要调整 4 个像素,来让显示更加完美.
// peter:需要检查Loc来调整editorComponent的location.
if (this.editorComponentLoc == null) {
this.editorComponent.setSize((int) Math.max(width, textPrefSize.getWidth() + 1), (int) height);
} else {
this.editorComponent.setSize((int) (Math.max(width, textPrefSize.getWidth() + 1) - this.editorComponentLoc.getX()), (int) (height - this.editorComponentLoc.getY()));
}
} else {
if (this.editorComponentLoc == null) {
this.editorComponent.setSize((int) width, (int) height);
} else {
this.editorComponent.setSize((int) (width - this.editorComponentLoc.getX()), (int) (height - this.editorComponentLoc.getY()));
}
}
}
// CellEditorListener, 当开始编辑的时候,这个Listener会被加入其中.停止编辑后这个listener会被删除.
private CellEditorListener innerCellEditorListener = new CellEditorListener() {
/**
* This tells the listeners the editor has stopped editing
*/
public void editingStopped(CellEditorEvent evt) {
Grid.this.stopCellEditingInner(false);
// if(Grid.this.)
}
/**
* This tells the listeners the editor has canceled editing
*/
public void editingCanceled(CellEditorEvent evt) {
Grid.this.cancelEditing();
}
};
// FloatEditorListener, 当开始编辑的时候,这个Listener会被加入其中.停止编辑后这个listener会被删除.
private FloatEditorListener innerFloatEditorListener = new FloatEditorListener() {
/**
* This tells the listeners the editor has stopped editing
*/
public void editingStopped(FloatEditorEvent evt) {
Grid.this.stopFloatEditingInner(false);
}
/**
* This tells the listeners the editor has canceled editing
*/
public void editingCanceled(FloatEditorEvent evt) {
Grid.this.cancelEditing();
}
};
/**
* @param dragType
*/
public void setDragType(int dragType) {
this.dragType = dragType;
}
/**
* @return
*/
public int getDragType() {
return dragType;
}
/**
* @param dragRectangle
*/
public void setDragRectangle(Rectangle dragRectangle) {
this.dragRectangle = dragRectangle;
}
/**
* @return
*/
public Rectangle getDragRectangle() {
return dragRectangle;
}
/**
* @param x
* @param y
*/
public void setTooltipLocation(double x, double y) {
if (tooltipLocation == null) {
tooltipLocation = new Point();
}
this.tooltipLocation.setLocation(x, y);
}
// @Override
// public void requestFocus() {
// super.requestFocus();
// }
}