用GEF做表格设计时,需要有合并单元格的功能,合并之前首先要判断所选区域是不是一个矩形(只有所选区域是矩形才执行合并操作),开发过程中,构思了一个高效简便的算法来完成这个判断,好了,接下来与大家分享此算法:
原理:如果所选区域是一个矩形,那么应满足以下等式:
selectedCellCount=(maxRowId-minRowId+1)*( maxColId-minColId+1)
其中:selectedCellCount为所选区域内所有单元格数量,如果所选区域内含有以前合并过的单元格,则取合并前的单元格数,即最小单位的单元格。
maxRowId为所选区域最大行号,maxRowId为所选区域最小行号
maxColId为所选区域最大列号,maxColId为所选区域最小列号
如:
所选区域为(2,2),(2,3)(3,2)(3,3) 则最大行号为3,最小行号为2,最大列号为3,最小列号为2 ,等式为:4=(3-2+1)×(3-2+1)
实现过程: 所选区域内的单元格数 是可以通过viewer.getSelectedEditParts().size()得到的,需要考虑的是如果该区域内含有已合并的单元格,要取得合并之前的单元格数,计入所选单元格数;接下来就是遍历viewer.getSelectedEditParts()取得最大行号、最小行号、最大列号、最小列号;最后完成等式的比较。
实现代码如下:
protected boolean calculateEnabled() {
DiagramEditor ed = (DiagramEditor) editor;
GraphicalViewer viewer = ed.getViewer();
List<?> parts = viewer.getSelectedEditParts();
TableModel table = null;
int selectedCellCount=parts.size();
if (selectedCellCount < 2)
return false;
int maxRowId = 0;
int minRowId = 100;
int maxColId = 0;
int minColId = 100;
for (Object opart : parts) {
EditPart part=(EditPart)opart;
if (!(part.getParent() instanceof TableEditPart))
return false;
else {
if (table == null)
table = (TableModel) part.getParent().getModel();
CellModel cell = (CellModel) part.getModel();
//如果单元格合并过,取得最初的单元格数,再加入所选单元格数
int colSpan = cell.getData().horizontalSpan;
int rowSpan = cell.getData().verticalSpan;
int cellCount=colSpan*rowSpan;
selectedCellCount=selectedCellCount+cellCount-1;
RowModel row = (RowModel) cell.getParent();
int rowId = table.getChildren().indexOf(row);
int colId = row.getChildren().indexOf(cell);
//判断当前行号、当前列号是否大于最大行号、最大列号,大于的话替换掉现有的最大行号、最大列号
if(minColId>colId)minColId=colId;
if(minRowId>rowId)minRowId=rowId;
//如果单元格合并过,取行号、列号时也都要处理
if (rowSpan>1) rowId=rowId+rowSpan-1;
if (colSpan>1) colId=colId+colSpan-1;
if(maxRowId<rowId)maxRowId=rowId;
if(maxColId<colId)maxColId=colId;
}
}
int calculateCellCount=(maxRowId-minRowId+1)*(maxColId-minColId+1);
if (selectedCellCount!=calculateCellCount) return false;
return true;
}
运行效果如下:按住Ctrl 多选单元格,所选区域为矩形允许合并:
所选区域为非矩形不允许合并: