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
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(); |
|
} |