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

514 lines
20 KiB

package com.fr.grid;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.lang.reflect.Method;
import javax.swing.JScrollBar;
import javax.swing.JToolTip;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import com.fr.base.BaseUtils;
import com.fr.base.DynamicUnitList;
import com.fr.base.FRContext;
import com.fr.base.ScreenResolution;
import com.fr.base.Utils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.general.Inter;
import com.fr.grid.selection.CellSelection;
import com.fr.grid.selection.FloatSelection;
import com.fr.grid.selection.Selection;
import com.fr.report.elementcase.ElementCase;
import com.fr.stable.ColumnRow;
import com.fr.stable.Constants;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.UNIT;
import com.fr.design.utils.gui.GUICoreUtils;
/**
* @editor zhou
* @since 2012-3-23上午11:54:14
*/
public abstract class AbstractGridHeaderMouseHandler extends MouseInputAdapter {
protected static final int SEPARATOR_GAP = 5;
private GridHeader gHeader;
private int dragType = GridUtils.DRAG_NONE;
//james 是否为选定多行的drag
private boolean isMultiSelectDragPermited = false;
private int startMultiSelectIndex = 0;
private int endMultiSelectIndex = 0;
// james
private boolean isDragPermited = false;
private int dragIndex = 0;
private JToolTip tip = null;
private JWindow tipWindow = null;
protected int resolution = ScreenResolution.getScreenResolution();
public AbstractGridHeaderMouseHandler(GridHeader gHeader) {
this.gHeader = gHeader;
if (gHeader instanceof GridColumn){
this.resolution = ((GridColumn)gHeader).getResolution();
}else {
this.resolution = ((GridRow)gHeader).getResolution();
}
}
public void setStartMultiSelectIndex(int index) {
this.startMultiSelectIndex = index;
}
public void setEndMultiSelectIndex(int index) {
this.endMultiSelectIndex = index;
}
protected abstract DynamicUnitList getSizeList(ElementCase elCase);
protected abstract String methodName();
protected abstract int getScrollValue(ElementCasePane casePane);
protected abstract int getScrollExtent(ElementCasePane casePane);
protected abstract int getBeginValue(ElementCasePane casePane);
protected abstract String getSelectedHeaderTooltip(int selectedSize);
/**
* Checks whether is on zero separator line.
*/
protected abstract boolean isOnSeparatorLineIncludeZero(MouseEvent evt, double tmpSize2, double tmpIncreaseSize);
protected abstract boolean between(MouseEvent evt, double from, double to);
/**
* Checks whether is on normal separator line.
*/
protected abstract boolean isOnNormalSeparatorLine(MouseEvent evt, double tmpSize2);
private abstract class ScrollAction {
public abstract boolean run(MouseEvent evt, int index, double tmpSize1, double tmpSize2, int tmpIncreaseSize, int oldEndValueSize, ElementCase report, DynamicUnitList sizeList);
}
private ScrollAction DRAG_ACTION = new ScrollAction() {
@Override
public boolean run(MouseEvent evt, int index, double tmpSize1, double tmpSize2, int tmpIncreaseSize, int oldEndValueSize, ElementCase report, DynamicUnitList sizeList) {
// int resolution = ScreenResolution.getScreenResolution();
// richer:这边这么做的原因是调整了行高列宽后需要通知聚合块改变边界
Method method = null;
try {
method = ElementCase.class.getMethod(methodName(), int.class, UNIT.class);
} catch (Exception e) {
FRContext.getLogger().error(e.getMessage(), e);
}
if (between(evt, tmpSize1, tmpSize2)) {
if (index >= dragIndex) {
try {
method.invoke(report, dragIndex, FU.valueOfPix(evtOffset(evt, oldEndValueSize), resolution));
} catch (Exception e) {
FRContext.getLogger().error(e.getMessage(), e);
}
//sizeList.set(dragIndex, FU.valueOfPix(evtOffset(evt, oldEndValueSize), resolution));
} else {
try {
method.invoke(report, index, FU.valueOfPix(evtOffset(evt, (int) tmpSize1), resolution));
} catch (Exception e) {
FRContext.getLogger().error(e.getMessage(), e);
}
//sizeList.set(index, FU.valueOfPix(evtOffset(evt, (int)tmpSize1), resolution));
// from all to do.
for (int h = (dragIndex - 1); h > index; h--) {
try {
method.invoke(report, h, UNIT.ZERO);
} catch (Exception e) {
FRContext.getLogger().error(e.getMessage(), e);
}
//sizeList.set(h, UNIT.ZERO);
}
}
return true;
}
return false;
}
};
private ScrollAction PRESS_ACTION = new ScrollAction() {
@Override
public boolean run(MouseEvent evt, int index, double tmpSize1, double tmpSize2, int tmpIncreaseSize, int oldEndValueSize, ElementCase report, DynamicUnitList sizeList) {
// int resolution = ScreenResolution.getScreenResolution();
if (isOnSeparatorLineIncludeZero(evt, tmpSize2, tmpIncreaseSize) || isOnNormalSeparatorLine(evt, tmpSize2)) {
dragType = GridUtils.DRAG_CELL_SIZE;
isDragPermited = true;
dragIndex = index;
showToolTip(evt, createToolTipString(sizeList.get(dragIndex).toPixD(resolution), sizeList.getRangeValue(0, dragIndex + 1).toPixD(resolution)));
return true;
}
if (between(evt, tmpSize1, tmpSize2)) {
dragType = GridUtils.DRAG_SELECT_UNITS;
isMultiSelectDragPermited = true;
startMultiSelectIndex = index;
showToolTip(evt, getSelectedHeaderTooltip(1));
return true;
}
return false;
}
};
private void iterateScrollBar(ElementCasePane ePane, MouseEvent evt, ScrollAction action) {
ElementCase report = ePane.getEditingElementCase();
DynamicUnitList sizeList = getSizeList(report);
int scrollValue = getScrollValue(ePane);
int scrollExtent = getScrollExtent(ePane);
int endValue = scrollValue + scrollExtent + 1;
int beginValue = getBeginValue(ePane);
double tmpSize1 = 0;
double tmpSize2;
double tmpIncreaseSize = 0;
double oldEndValueSize = 0;
// int resolution = ScreenResolution.getScreenResolution();
for (int index = beginValue; index < endValue; index++) { // denny:
// beginValue
if (index == 0) {
index = scrollValue;
}
tmpSize1 += tmpIncreaseSize;
tmpIncreaseSize = sizeList.get(index).toPixD(resolution);
tmpSize2 = tmpSize1 + Math.max(1, tmpIncreaseSize);
if (index == dragIndex) {
oldEndValueSize = tmpSize1 + 1;
}
if (action.run(evt, index, tmpSize1, tmpSize2, (int) tmpIncreaseSize, (int) oldEndValueSize, report, sizeList)) {
break;
}
}
}
protected abstract UIPopupMenu createPopupMenu(ElementCasePane ePane, MouseEvent evt, int index);
/**
* Invoked when a mouse button has been pressed on a component.
*/
@Override
public void mousePressed(MouseEvent evt) {
if (!this.gHeader.isEnabled()) {
return;
}
ElementCasePane ePane = this.gHeader.getElementCasePane();
ePane.getGrid().stopEditing();// james 停止当前的所有编辑
// peter:选中格子位置.
ColumnRow selectedCellPoint = GridUtils.getAdjustEventColumnRow_withresolution(ePane, evt.getX(), evt.getY(),resolution);
iterateScrollBar(ePane, evt, PRESS_ACTION);
// popu menu
if (SwingUtilities.isRightMouseButton(evt)) {
Selection cs = ePane.getSelection();
resetSelectionByRightButton(selectedCellPoint, cs, ePane);
UIPopupMenu popupMenu = createPopupMenu(ePane, evt, Math.max(dragIndex, Math.max(this.startMultiSelectIndex, this.endMultiSelectIndex)));
if (popupMenu != null) {
GUICoreUtils.showPopupMenu(popupMenu, gHeader, evt.getX() + 1, evt.getY() + 1);
}
} else {
if (dragType == GridUtils.DRAG_SELECT_UNITS) {
if (evt.isShiftDown()) {// shift selection.
this.doShiftSelectHeader(ePane, evt.getX(), evt.getY());
} else {
this.endMultiSelectIndex = this.startMultiSelectIndex;
resetGridSelectionBySelect(getColumnOrRowByGridHeader(selectedCellPoint), ePane);
}
}
}
// p:在另外一个线程里面话,而且延迟画.
ePane.repaint();
}
protected abstract void resetSelectionByRightButton(ColumnRow mouseSelectedColumnRow, Selection cs, ElementCasePane ePane);
protected abstract int doChooseFrom();
/**
* 选中多行或者多列
*
* @param ePane
* @param evtX
* @param evtY
*/
private void doShiftSelectHeader(ElementCasePane ePane, double evtX, double evtY) {
ColumnRow selectedCellPoint = GridUtils.getAdjustEventColumnRow_withresolution(ePane, evtX, evtY, resolution);
int selectedCellPointX = selectedCellPoint.getColumn();// column.
int selectedCellPointY = selectedCellPoint.getRow();// row.
CellSelection cs = ((CellSelection) ePane.getSelection()).clone();
int tempOldSelectedCellX = cs.getColumn();
int tempOldSelectedCellY = cs.getRow();
int column = 0;
int row = 0;
int columnSpan = 0;
int rowSpan = 0;
//august 同列和同行
if (selectedCellPointX == tempOldSelectedCellX) {
column = selectedCellPointX;
row = Math.min(selectedCellPointY, tempOldSelectedCellY);
columnSpan = cs.getColumnSpan();
rowSpan = Math.abs(selectedCellPointY - tempOldSelectedCellY) + 1;
} else if (selectedCellPointY == tempOldSelectedCellY) {
row = selectedCellPointY;
column = Math.min(selectedCellPointX, tempOldSelectedCellX);
columnSpan = Math.abs(selectedCellPointX - tempOldSelectedCellX) + 1;
rowSpan = cs.getRowSpan();
}
Rectangle newrectangle = new Rectangle(column, row, columnSpan, rowSpan);
cs.setBounds(column, row, columnSpan, rowSpan);
cs.clearCellRectangles(cs.getCellRectangleCount() - 1);
cs.addCellRectangle(newrectangle);
cs.setSelectedType(doChooseFrom());
ePane.setSelection(cs);
ePane.ensureColumnRowVisible(selectedCellPointX, selectedCellPointY);
}
protected abstract Rectangle resetSelectedBoundsByShift(Rectangle editRectangle, ColumnRow selectedCellPoint, ElementCasePane ePane);
protected abstract void resetGridSelectionBySelect(int index, ElementCasePane ePane);
private String createToolTipString(double doubleValue, double totalDoubleValue) {
int unitType = DesignerEnvManager.getEnvManager().getReportLengthUnit();
// int resolution = ScreenResolution.getScreenResolution();
FU ulen = FU.valueOfPix((int) doubleValue, resolution);
FU tulen = FU.valueOfPix((int) totalDoubleValue, resolution);
String unit;
double len, tlen;
if (unitType == Constants.UNIT_PT) {
len = ulen.toPTValue4Scale2();
tlen = tulen.toPTValue4Scale2();
unit = Inter.getLocText("Unit_PT");
} else if (unitType == Constants.UNIT_CM) {
len = ulen.toCMValue4Scale2();
tlen = tulen.toCMValue4Scale2();
unit = Inter.getLocText("Unit_CM");
} else if (unitType == Constants.UNIT_INCH) {
len = ulen.toINCHValue4Scale3();
tlen = tulen.toINCHValue4Scale3();
unit = Inter.getLocText("Unit_INCH");
} else {
len = ulen.toMMValue4Scale2();
tlen = tulen.toMMValue4Scale2();
unit = Inter.getLocText("Unit_MM");
}
StringBuilder sb = new StringBuilder();
sb.append(String.format("%.2f", new Double(len)))
.append('/').append(String.format("%.2f", new Double(tlen)))
.append(unit).append('(')
.append((int)(doubleValue)).append('/')
.append((int)(totalDoubleValue))
.append(Inter.getLocText("px"))
.append(')');
return sb.toString();
}
private void showToolTip(MouseEvent evt, String text) {
if (tipWindow == null) {
tipWindow = new JWindow();
tip = this.gHeader.createToolTip();
tipWindow.getContentPane().add(tip, BorderLayout.CENTER);
}
tip.setTipText(text);
Point tipLocation = getTipLocationByMouseEvent(evt, gHeader, tip.getPreferredSize());
tipWindow.setLocation(tipLocation.x, tipLocation.y);
tipWindow.pack();
tipWindow.setVisible(true);
}
protected abstract Point getTipLocationByMouseEvent(MouseEvent evt, GridHeader gHeader, Dimension tipPreferredSize);
private void hideToolTip() {
if (tipWindow != null) {
tipWindow.setVisible(false);
}
}
@Override
public void mouseReleased(MouseEvent evt) {
if (!this.gHeader.isEnabled()) {
return;
}
ElementCasePane ePane = gHeader.getElementCasePane();
ePane.getGrid().stopEditing();// james 停止当前的所有编辑
this.isMultiSelectDragPermited = false;
this.isDragPermited = false;
this.hideToolTip();// hide tooltip first.
if (dragType == GridUtils.DRAG_CELL_SIZE) {// read changed column width.
// 需要revalidate scrollbar.
JScrollBar vBar = ePane.getVerticalScrollBar();
if (vBar != null) {
vBar.setValue(vBar.getValue());
}
JScrollBar hBar = ePane.getHorizontalScrollBar();
if (hBar != null) {
hBar.setValue(hBar.getValue());
}
ePane.fireTargetModified();
}
dragType = GridUtils.DRAG_NONE;
this.dragIndex = 0;
}
protected abstract int[] getGridSelectionIndices(CellSelection cs);
@Override
public void mouseDragged(MouseEvent evt) {
if (!gHeader.isEnabled() || this.dragType == GridUtils.DRAG_NONE || SwingUtilities.isRightMouseButton(evt)) {
return;
}
ElementCasePane ePane = gHeader.getElementCasePane();
ElementCase report = ePane.getEditingElementCase();
if (ePane.getSelection() instanceof FloatSelection) {
return;
}
CellSelection cs = ((CellSelection) ePane.getSelection()).clone();
ePane.getGrid().stopEditing();// james 停止当前的所有编辑
if (this.dragType == GridUtils.DRAG_SELECT_UNITS) {// james 多列选定时
if (!this.isMultiSelectDragPermited) {
return;
}
ColumnRow selectedCellPoint = GridUtils.getAdjustEventColumnRow_withresolution(ePane, evt.getX(), evt.getY(), resolution);
endMultiSelectIndex = getColumnOrRowByGridHeader(selectedCellPoint);
resetGridSelectionByDrag(cs, ePane, startMultiSelectIndex, endMultiSelectIndex);
cs.setSelectedType(doChooseFrom());
ePane.setSelection(cs);
if (!ePane.mustInVisibleRange()) {
ePane.ensureColumnRowVisible(selectedCellPoint.getColumn(), selectedCellPoint.getRow());
}
this.setToolTipText2(this.getSelectedHeaderTooltip(Math.abs(startMultiSelectIndex - endMultiSelectIndex) + 1));
} else if (dragType == GridUtils.DRAG_CELL_SIZE) {
//权限编辑状态不可以改变行列的宽度
if (BaseUtils.isAuthorityEditing()) {
return;
}
if (!(isDragPermited)) {
return;
}
iterateScrollBar(ePane, evt, DRAG_ACTION);
DynamicUnitList sizeList = getSizeList(report);
// int resolution = ScreenResolution.getScreenResolution();
this.setToolTipText2(this.createToolTipString(sizeList.get(dragIndex).toPixD(resolution), sizeList.getRangeValue(0, dragIndex + 1).toPixD(resolution)));
}
ePane.repaint();
}
protected abstract void resetGridSelectionByDrag(
CellSelection gridSelection, ElementCasePane reportPane,
int startMultiSelectIndex, int endMultiSelectIndex
);
protected abstract int evtOffset(MouseEvent evt, int offset);
protected abstract int getColumnOrRowByGridHeader(ColumnRow selectedCellPoint);
private void setToolTipText2(String text) {
if (tip == null) {
return;
}
tip.setTipText(text);
tip.setSize(tip.getPreferredSize());
tipWindow.pack();
tipWindow.repaint();
}
@Override
public void mouseMoved(MouseEvent evt) {
if (!gHeader.isEnabled()) {
return;
}
ElementCasePane ePane = gHeader.getElementCasePane();
ElementCase report = ePane.getEditingElementCase();
gHeader.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(BaseUtils.readImage(
"/com/fr/base/images/cell/cursor/" + nameOfSelectCursorGIF() + ".gif"
), new Point(16, 16), nameOfSelectCursorGIF()));
DynamicUnitList sizeList = getSizeList(report);
int scrollValue = getScrollValue(ePane);
int scrollExtent = getScrollExtent(ePane);
int endValue = scrollValue + scrollExtent + 1;
int beginValue = getBeginValue(ePane);
// draw column
double tmpSize1 = 0;
double tmpSize2;
double tmpIncreaseSize = 0;
// int resolution = ScreenResolution.getScreenResolution();
for (int i = beginValue; i < endValue; i++) {
if (i == 0) {
i = scrollValue;
}
// ajust width.
tmpSize1 += tmpIncreaseSize;
tmpIncreaseSize = sizeList.get(i).toPixD(resolution);
tmpSize2 = tmpIncreaseSize <= 0 ? tmpSize1 + 1 : tmpSize1 + tmpIncreaseSize;
if (BaseUtils.isAuthorityEditing()) {
break;
}
if (this.isOnSeparatorLineIncludeZero(evt, tmpSize2, tmpIncreaseSize)) {
gHeader.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(BaseUtils.readImage(
"/com/fr/base/images/cell/cursor/" + nameOfSplitCursorGIF() + ".gif"
), new Point(16, 16), nameOfSplitCursorGIF()));
break;
} else if (this.isOnNormalSeparatorLine(evt, tmpSize2)) {
gHeader.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(BaseUtils.readImage(
"/com/fr/base/images/cell/cursor/" + nameOfMoveCursorGIF() + ".gif"
), new Point(16, 16), nameOfMoveCursorGIF()));
break;
}
}
}
protected abstract String nameOfSelectCursorGIF();
protected abstract String nameOfSplitCursorGIF();
protected abstract String nameOfMoveCursorGIF();
}