GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。
- package org.dxj.guitools.gridbagtable;
- import java.awt.Component;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.util.Enumeration;
- import java.util.EventObject;
- import javax.swing.DefaultCellEditor;
- import javax.swing.JTable;
- import javax.swing.SwingUtilities;
- import javax.swing.event.TableModelEvent;
- import javax.swing.table.AbstractTableModel;
- import javax.swing.table.TableColumn;
- import javax.swing.table.TableColumnModel;
- /**
- * @author 15860102@qq.com
- */
- public class GridBagTable extends JTable{
- GridBagModel gridBagModel;
- public GridBagModel getGridBagModel() {
- return gridBagModel;
- }
- public void setGridBagModel(GridBagModel gridBagModel){
- if( gridBagModel != null && gridBagModel != this.gridBagModel )
- this.gridBagModel = gridBagModel;
- }
- public GridBagTable(AbstractTableModel dm){
- super(dm);
- getTableHeader().setReorderingAllowed(false);
- gridBagModel = new DefaultGridBagTableModel(dm);
- getColumnModel().setColumnSelectionAllowed(true);
- }
- private void updateSubComponentUI(Object componentShell) {
- if (componentShell == null) {
- return;
- }
- Component component = null;
- if (componentShell instanceof Component) {
- component = (Component)componentShell;
- }
- if (componentShell instanceof DefaultCellEditor) {
- component = ((DefaultCellEditor)componentShell).getComponent();
- }
- if (component != null) {
- SwingUtilities.updateComponentTreeUI(component);
- }
- }
- public void updateUI() {
- // Update the UIs of the cell renderers, cell editors and header renderers.
- TableColumnModel cm = getColumnModel();
- for(int column = 0; column < cm.getColumnCount(); column++) {
- TableColumn aColumn = cm.getColumn(column);
- updateSubComponentUI(aColumn.getCellRenderer());
- updateSubComponentUI(aColumn.getCellEditor());
- updateSubComponentUI(aColumn.getHeaderRenderer());
- }
- // Update the UIs of all the default renderers.
- Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
- while (defaultRenderers.hasMoreElements()) {
- updateSubComponentUI(defaultRenderers.nextElement());
- }
- // Update the UIs of all the default editors.
- Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
- while (defaultEditors.hasMoreElements()) {
- updateSubComponentUI(defaultEditors.nextElement());
- }
- // Update the UI of the table header
- if (tableHeader != null && tableHeader.getParent() == null) {
- tableHeader.updateUI();
- }
- setUI(new GridBagTableUI());
- }
- public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
- return super.getCellRect(row, column, includeSpacing);
- }
- public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
- Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
- int cols = gridBagModel.getColumnGrid(row, column);
- TableColumnModel cm = getColumnModel();
- for( int n=1; n<cols; n++)
- cellRect.width += cm.getColumn(column+n).getWidth();
- int rows = gridBagModel.getRowGrid(row, column);
- for( int n=1; n<rows; n++)
- cellRect.height += getRowHeight(row+n);
- return cellRect;
- }
- public void tableChanged(TableModelEvent e){
- super.tableChanged(e);
- //TODO
- }
- public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
- if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
- repaint();
- return true;
- }
- return false;
- }
- public boolean mergeCells(int[] rows, int[] columns){
- if( gridBagModel.mergeCells(rows, columns)){
- repaint();
- return true;
- }
- return false;
- }
- public boolean spliteCellAt(int row, int column){
- if( gridBagModel.spliteCellAt(row, column)){
- repaint();
- return true;
- }
- return false;
- }
- public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
- if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
- super.changeSelection(rowIndex, columnIndex, toggle, extend);
- Point p;
- for( int row = rowIndex; row >= 0; row-- ){
- for( int col = columnIndex; col >= 0; col-- ){
- p = gridBagModel.getGrid(row, col);
- //p = ((Point)((Vector)rowVector.get(row)).get(col));
- if( col + p.x > columnIndex && row + p.y > rowIndex){
- rowIndex = row;
- columnIndex = col;
- break;
- }
- }
- }
- super.changeSelection(rowIndex, columnIndex, toggle, extend);
- repaint();
- }
- public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
- if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
- return super.editCellAt(rowIndex, columnIndex, e);
- Point p;
- for( int row = rowIndex; row >= 0; row-- ){
- for( int col = columnIndex; col >= 0; col-- ){
- p = gridBagModel.getGrid(row, col);
- if( col + p.x > columnIndex && row + p.y > rowIndex){
- rowIndex = row;
- columnIndex = col;
- break;
- }
- }
- }
- return super.editCellAt(rowIndex, columnIndex, e);
- }
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* @author 15860102@qq.com
*/
public class GridBagTable extends JTable{
GridBagModel gridBagModel;
public GridBagModel getGridBagModel() {
return gridBagModel;
}
public void setGridBagModel(GridBagModel gridBagModel){
if( gridBagModel != null && gridBagModel != this.gridBagModel )
this.gridBagModel = gridBagModel;
}
public GridBagTable(AbstractTableModel dm){
super(dm);
getTableHeader().setReorderingAllowed(false);
gridBagModel = new DefaultGridBagTableModel(dm);
getColumnModel().setColumnSelectionAllowed(true);
}
private void updateSubComponentUI(Object componentShell) {
if (componentShell == null) {
return;
}
Component component = null;
if (componentShell instanceof Component) {
component = (Component)componentShell;
}
if (componentShell instanceof DefaultCellEditor) {
component = ((DefaultCellEditor)componentShell).getComponent();
}
if (component != null) {
SwingUtilities.updateComponentTreeUI(component);
}
}
public void updateUI() {
// Update the UIs of the cell renderers, cell editors and header renderers.
TableColumnModel cm = getColumnModel();
for(int column = 0; column < cm.getColumnCount(); column++) {
TableColumn aColumn = cm.getColumn(column);
updateSubComponentUI(aColumn.getCellRenderer());
updateSubComponentUI(aColumn.getCellEditor());
updateSubComponentUI(aColumn.getHeaderRenderer());
}
// Update the UIs of all the default renderers.
Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
while (defaultRenderers.hasMoreElements()) {
updateSubComponentUI(defaultRenderers.nextElement());
}
// Update the UIs of all the default editors.
Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
while (defaultEditors.hasMoreElements()) {
updateSubComponentUI(defaultEditors.nextElement());
}
// Update the UI of the table header
if (tableHeader != null && tableHeader.getParent() == null) {
tableHeader.updateUI();
}
setUI(new GridBagTableUI());
}
public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
return super.getCellRect(row, column, includeSpacing);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
int cols = gridBagModel.getColumnGrid(row, column);
TableColumnModel cm = getColumnModel();
for( int n=1; n<cols; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
int rows = gridBagModel.getRowGrid(row, column);
for( int n=1; n<rows; n++)
cellRect.height += getRowHeight(row+n);
return cellRect;
}
public void tableChanged(TableModelEvent e){
super.tableChanged(e);
//TODO
}
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
repaint();
return true;
}
return false;
}
public boolean mergeCells(int[] rows, int[] columns){
if( gridBagModel.mergeCells(rows, columns)){
repaint();
return true;
}
return false;
}
public boolean spliteCellAt(int row, int column){
if( gridBagModel.spliteCellAt(row, column)){
repaint();
return true;
}
return false;
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
super.changeSelection(rowIndex, columnIndex, toggle, extend);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
//p = ((Point)((Vector)rowVector.get(row)).get(col));
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
repaint();
}
public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
return super.editCellAt(rowIndex, columnIndex, e);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
return super.editCellAt(rowIndex, columnIndex, e);
}
}
- package org.dxj.guitools.gridbagtable;
- import java.awt.Point;
- public interface GridBagModel {
- //格子处于正常状态
- int DEFAULT = 0;
- //格子合并了其他的格子
- int MERGE = 1;
- //格子被其他格子合并
- int COVERED = -1;
- /**
- * @param row 行
- * @param column 列
- * @return 该单元格在行、列的跨度
- */
- Point getGrid(int row, int column);
- /**
- * 在Y轴方向的跨度
- * @param row
- * @param column
- * @return
- */
- int getRowGrid(int row, int column);
- /**
- * 在X轴方向的跨度
- * @param row
- * @param column
- * @return
- */
- int getColumnGrid(int row, int column);
- /**
- * @param rows 行集合
- * @param columns 列集合
- * @return 单元格集合是否可以合并在一起
- */
- boolean canMergeCells(int[] rows, int[] columns);
- /**
- * 判断该单元格状态
- * @param row
- * @param column
- * @return MERGE|DEFAULT|COVERED
- */
- int getCellState(int row, int column);
- /**
- * 将单元格集合合并
- * @param startRow 开始行
- * @param endRow 结束行
- * @param startColumn 开始列
- * @param endColumn 结束列
- * @return 是否合并成功
- */
- boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
- /**
- * 将单元格集合合并
- * @param rows 行集合
- * @param columns 列集合
- * @return 是否合并成功
- */
- boolean mergeCells(int[] rows, int[] columns);
- /**
- * 拆分单元格
- * @param row 行
- * @param column 列
- * @return 是否拆分成功
- */
- boolean spliteCellAt(int row, int column);
- /**
- * 清除 所有合并
- */
- void clearMergence();
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
public interface GridBagModel {
//格子处于正常状态
int DEFAULT = 0;
//格子合并了其他的格子
int MERGE = 1;
//格子被其他格子合并
int COVERED = -1;
/**
* @param row 行
* @param column 列
* @return 该单元格在行、列的跨度
*/
Point getGrid(int row, int column);
/**
* 在Y轴方向的跨度
* @param row
* @param column
* @return
*/
int getRowGrid(int row, int column);
/**
* 在X轴方向的跨度
* @param row
* @param column
* @return
*/
int getColumnGrid(int row, int column);
/**
* @param rows 行集合
* @param columns 列集合
* @return 单元格集合是否可以合并在一起
*/
boolean canMergeCells(int[] rows, int[] columns);
/**
* 判断该单元格状态
* @param row
* @param column
* @return MERGE|DEFAULT|COVERED
*/
int getCellState(int row, int column);
/**
* 将单元格集合合并
* @param startRow 开始行
* @param endRow 结束行
* @param startColumn 开始列
* @param endColumn 结束列
* @return 是否合并成功
*/
boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
/**
* 将单元格集合合并
* @param rows 行集合
* @param columns 列集合
* @return 是否合并成功
*/
boolean mergeCells(int[] rows, int[] columns);
/**
* 拆分单元格
* @param row 行
* @param column 列
* @return 是否拆分成功
*/
boolean spliteCellAt(int row, int column);
/**
* 清除 所有合并
*/
void clearMergence();
}
- package org.dxj.guitools.gridbagtable;
- import java.awt.Point;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Vector;
- import javax.swing.event.TableModelEvent;
- import javax.swing.event.TableModelListener;
- import javax.swing.table.AbstractTableModel;
- public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
- protected AbstractTableModel model;
- protected List<List<Point>> gridInfo;
- DefaultGridBagTableModel(AbstractTableModel model){
- gridInfo = new Vector<List<Point>>();
- setTableModel(model);
- }
- public void setTableModel(AbstractTableModel model){
- if( model != null && model != this.model ){
- if( this.model != null )
- this.model.removeTableModelListener(this);
- //防止多次添加监听器
- model.removeTableModelListener(this);
- model.addTableModelListener(this);
- this.model = model;
- clearMergence();
- }
- }
- public void clearMergence(){
- if( gridInfo == null )
- gridInfo = new Vector<List<Point>>();
- else
- gridInfo.clear();
- if( model == null )
- return;
- //初始化,每个格子占的格子数为(1,1);
- for(int row=model.getRowCount(); --row>=0;){
- List<Point> infos = new Vector<Point>();
- gridInfo.add(infos);
- for(int col=model.getColumnCount(); --col>=0;){
- infos.add(getDefaultPoint());
- }
- }
- }
- public Point getDefaultPoint(){
- return new Point(1,1);
- }
- @Override
- public boolean canMergeCells(int[] rows, int[] columns) {
- if( rows == null || columns == null ) return false;
- Arrays.sort(rows);
- for(int index=0; index<rows.length-1; index++){
- if( rows[index+1] - rows[index] > 1 )
- return false;
- }
- Arrays.sort(columns);
- for(int index=0; index<columns.length-1; index++){
- if( columns[index+1] - columns[index] > 1 )
- return false;
- }
- return true;
- }
- @Override
- public int getCellState(int row, int column) {
- Point grid = getGrid(row, column);
- if( grid == null ) return DEFAULT;
- if( grid.x>1 || grid.y>1 )
- return MERGE;
- if( grid.x<=0 || grid.y<=0 )
- return COVERED;
- return DEFAULT;
- }
- @Override
- public int getColumnGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null )
- return point.x;
- }
- }
- return 1;
- }
- @Override
- public Point getGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- return gridRow.get(column);
- }
- }
- return getDefaultPoint();
- }
- @Override
- public int getRowGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null )
- return point.y;
- }
- }
- return 1;
- }
- protected boolean setGrid(int row, int column, Point grid) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null ){
- point.setLocation(grid);
- }
- else{
- gridRow.set(column, grid.getLocation());
- }
- return true;
- }
- }
- return false;
- }
- @Override
- public boolean spliteCellAt(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null ){
- point = point.getLocation();
- for(int a=0; a<point.y; a++){
- for(int b=0; b<point.x; b++){
- setGrid(row+a, column+b, getDefaultPoint());
- }
- }
- }
- else{
- gridRow.set(column, getDefaultPoint());
- }
- return true;
- }
- }
- return false;
- }
- @Override
- /**
- * table中发生行的添加和删除的时候需要修改该模型
- */
- public void tableChanged(TableModelEvent e) {
- //TODO
- }
- @Override
- public boolean mergeCells(int[] rows, int[] columns) {
- if( !canMergeCells(rows, columns) )
- return false;
- Arrays.sort(rows);
- Arrays.sort(columns);
- return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
- }
- @Override
- public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
- setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
- for(int row=startRow; row<=endRow; row++){
- for(int col=startColumn; col<=endColumn; col++){
- if(row==startRow&&col==startColumn)
- continue;
- else
- setGrid(row, col, new Point(COVERED,COVERED));
- }
- }
- return true;
- }
- public String toString(){
- if( gridInfo == null )
- return "";
- StringBuffer sb = new StringBuffer();
- for(List<Point> rowInfo : gridInfo ){
- for(Point grid : rowInfo){
- sb.append("["+grid.x+","+grid.y+"], ");
- }
- sb.append("\n");
- }
- return sb.toString();
- }
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
protected AbstractTableModel model;
protected List<List<Point>> gridInfo;
DefaultGridBagTableModel(AbstractTableModel model){
gridInfo = new Vector<List<Point>>();
setTableModel(model);
}
public void setTableModel(AbstractTableModel model){
if( model != null && model != this.model ){
if( this.model != null )
this.model.removeTableModelListener(this);
//防止多次添加监听器
model.removeTableModelListener(this);
model.addTableModelListener(this);
this.model = model;
clearMergence();
}
}
public void clearMergence(){
if( gridInfo == null )
gridInfo = new Vector<List<Point>>();
else
gridInfo.clear();
if( model == null )
return;
//初始化,每个格子占的格子数为(1,1);
for(int row=model.getRowCount(); --row>=0;){
List<Point> infos = new Vector<Point>();
gridInfo.add(infos);
for(int col=model.getColumnCount(); --col>=0;){
infos.add(getDefaultPoint());
}
}
}
public Point getDefaultPoint(){
return new Point(1,1);
}
@Override
public boolean canMergeCells(int[] rows, int[] columns) {
if( rows == null || columns == null ) return false;
Arrays.sort(rows);
for(int index=0; index<rows.length-1; index++){
if( rows[index+1] - rows[index] > 1 )
return false;
}
Arrays.sort(columns);
for(int index=0; index<columns.length-1; index++){
if( columns[index+1] - columns[index] > 1 )
return false;
}
return true;
}
@Override
public int getCellState(int row, int column) {
Point grid = getGrid(row, column);
if( grid == null ) return DEFAULT;
if( grid.x>1 || grid.y>1 )
return MERGE;
if( grid.x<=0 || grid.y<=0 )
return COVERED;
return DEFAULT;
}
@Override
public int getColumnGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.x;
}
}
return 1;
}
@Override
public Point getGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
return gridRow.get(column);
}
}
return getDefaultPoint();
}
@Override
public int getRowGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.y;
}
}
return 1;
}
protected boolean setGrid(int row, int column, Point grid) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point.setLocation(grid);
}
else{
gridRow.set(column, grid.getLocation());
}
return true;
}
}
return false;
}
@Override
public boolean spliteCellAt(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point = point.getLocation();
for(int a=0; a<point.y; a++){
for(int b=0; b<point.x; b++){
setGrid(row+a, column+b, getDefaultPoint());
}
}
}
else{
gridRow.set(column, getDefaultPoint());
}
return true;
}
}
return false;
}
@Override
/**
* table中发生行的添加和删除的时候需要修改该模型
*/
public void tableChanged(TableModelEvent e) {
//TODO
}
@Override
public boolean mergeCells(int[] rows, int[] columns) {
if( !canMergeCells(rows, columns) )
return false;
Arrays.sort(rows);
Arrays.sort(columns);
return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
}
@Override
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
for(int row=startRow; row<=endRow; row++){
for(int col=startColumn; col<=endColumn; col++){
if(row==startRow&&col==startColumn)
continue;
else
setGrid(row, col, new Point(COVERED,COVERED));
}
}
return true;
}
public String toString(){
if( gridInfo == null )
return "";
StringBuffer sb = new StringBuffer();
for(List<Point> rowInfo : gridInfo ){
for(Point grid : rowInfo){
sb.append("["+grid.x+","+grid.y+"], ");
}
sb.append("\n");
}
return sb.toString();
}
}
- package org.dxj.guitools.gridbagtable;
- import java.awt.Color;
- import java.awt.Component;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.util.Enumeration;
- import javax.swing.BorderFactory;
- import javax.swing.JComponent;
- import javax.swing.JTable;
- import javax.swing.UIManager;
- import javax.swing.plaf.basic.BasicTableUI;
- import javax.swing.table.JTableHeader;
- import javax.swing.table.TableCellRenderer;
- import javax.swing.table.TableColumn;
- import javax.swing.table.TableColumnModel;
- public class GridBagTableUI extends BasicTableUI
- {
- public Dimension getPreferredSize(JComponent c) {
- long width = 0;
- Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
- while (enumeration.hasMoreElements()) {
- TableColumn aColumn = (TableColumn)enumeration.nextElement();
- width = width + aColumn.getPreferredWidth();
- }
- return createTableSize(width);
- }
- private Dimension createTableSize(long width) {
- int height = 0;
- int rowCount = table.getRowCount();
- if (rowCount > 0 && table.getColumnCount() > 0) {
- Rectangle r = table.getCellRect(rowCount-1, 0, true);
- height = r.y + r.height;
- }
- // Width is always positive. The call to abs() is a workaround for
- // a bug in the 1.1.6 JIT on Windows.
- long tmp = Math.abs(width);
- if (tmp > Integer.MAX_VALUE) {
- tmp = Integer.MAX_VALUE;
- }
- return new Dimension((int)tmp, height);
- }
- public void paint(Graphics g, JComponent c) {
- Rectangle clip = g.getClipBounds();
- Rectangle bounds = table.getBounds();
- // account for the fact that the graphics has already been translated
- // into the table's bounds
- bounds.x = bounds.y = 0;
- if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
- // this check prevents us from painting the entire table
- // when the clip doesn't intersect our bounds at all
- !bounds.intersects(clip)) {
- paintDropLines(g);
- return;
- }
- boolean ltr = table.getComponentOrientation().isLeftToRight();
- Point upperLeft = clip.getLocation();
- if (!ltr) {
- upperLeft.x++;
- }
- Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
- clip.y + clip.height);
- int rMin = table.rowAtPoint(upperLeft);
- int rMax = table.rowAtPoint(lowerRight);
- // This should never happen (as long as our bounds intersect the clip,
- // which is why we bail above if that is the case).
- if (rMin == -1) {
- rMin = 0;
- }
- // If the table does not have enough rows to fill the view we'll get -1.
- // (We could also get -1 if our bounds don't intersect the clip,
- // which is why we bail above if that is the case).
- // Replace this with the index of the last row.
- if (rMax == -1) {
- rMax = table.getRowCount()-1;
- }
- int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
- int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
- // This should never happen.
- if (cMin == -1) {
- cMin = 0;
- }
- // If the table does not have enough columns to fill the view we'll get -1.
- // Replace this with the index of the last column.
- if (cMax == -1) {
- cMax = table.getColumnCount()-1;
- }
- // Paint the grid.
- //paintGrid(g, rMin, rMax, cMin, cMax);
- // Paint the cells.
- paintCells(g, rMin, rMax, cMin, cMax);
- paintDropLines(g);
- }
- private void paintDropLines(Graphics g) {
- JTable.DropLocation loc = table.getDropLocation();
- if (loc == null) {
- return;
- }
- Color color = UIManager.getColor("Table.dropLineColor");
- Color shortColor = UIManager.getColor("Table.dropLineShortColor");
- if (color == null && shortColor == null) {
- return;
- }
- Rectangle rect;
- rect = getHDropLineRect(loc);
- if (rect != null) {
- int x = rect.x;
- int w = rect.width;
- if (color != null) {
- extendRect(rect, true);
- g.setColor(color);
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- }
- if (!loc.isInsertColumn() && shortColor != null) {
- g.setColor(shortColor);
- g.fillRect(x, rect.y, w, rect.height);
- }
- }
- rect = getVDropLineRect(loc);
- if (rect != null) {
- int y = rect.y;
- int h = rect.height;
- if (color != null) {
- extendRect(rect, false);
- g.setColor(color);
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- }
- if (!loc.isInsertRow() && shortColor != null) {
- g.setColor(shortColor);
- g.fillRect(rect.x, y, rect.width, h);
- }
- }
- }
- /*
- * Paints the grid lines within <I>aRect</I>, using the grid
- * color set with <I>setGridColor</I>. Paints vertical lines
- * if <code>getShowVerticalLines()</code> returns true and paints
- * horizontal lines if <code>getShowHorizontalLines()</code>
- * returns true.
- */
- private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
- g.setColor(table.getGridColor());
- Rectangle minCell = table.getCellRect(rMin, cMin, true);
- Rectangle maxCell = table.getCellRect(rMax, cMax, true);
- Rectangle damagedArea = minCell.union( maxCell );
- if (table.getShowHorizontalLines()) {
- int tableWidth = damagedArea.x + damagedArea.width;
- int y = damagedArea.y;
- for (int row = rMin; row <= rMax; row++) {
- y += table.getRowHeight(row);
- g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
- }
- }
- if (table.getShowVerticalLines()) {
- TableColumnModel cm = table.getColumnModel();
- int tableHeight = damagedArea.y + damagedArea.height;
- int x;
- if (table.getComponentOrientation().isLeftToRight()) {
- x = damagedArea.x;
- for (int column = cMin; column <= cMax; column++) {
- int w = cm.getColumn(column).getWidth();
- x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
- }
- } else {
- x = damagedArea.x;
- for (int column = cMax; column >= cMin; column--) {
- int w = cm.getColumn(column).getWidth();
- x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
- }
- }
- }
- }
- private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
- JTableHeader header = table.getTableHeader();
- TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
- TableColumnModel cm = table.getColumnModel();
- int columnMargin = cm.getColumnMargin();
- Rectangle cellRect;
- TableColumn aColumn;
- int columnWidth;
- if (table.getComponentOrientation().isLeftToRight()) {
- for(int row = rMin; row <= rMax; row++) {
- if( table instanceof GridBagTable )
- cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
- else
- cellRect = table.getCellRect(row, cMin, false);
- for(int column = cMin; column <= cMax; column++) {
- aColumn = cm.getColumn(column);
- columnWidth = aColumn.getWidth();
- //TODO
- cellRect.width = columnWidth - columnMargin;
- int oldHeight = cellRect.height;
- if( table instanceof GridBagTable ){
- if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
- cellRect.width = 0;
- cellRect.height = 0;
- }
- else{
- int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
- if( h >1 ){
- for( int n=1; n<h; n++)
- cellRect.width += cm.getColumn(column+n).getWidth();
- }
- int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
- if( v >1 ){
- for( int n=1; n<v; n++)
- cellRect.height += table.getRowHeight(row+n);
- }
- }
- }
- if (aColumn != draggedColumn) {
- paintCell(g, cellRect, row, column);
- }
- cellRect.height = oldHeight;
- cellRect.x += columnWidth;
- }
- }
- } else {
- for(int row = rMin; row <= rMax; row++) {
- cellRect = table.getCellRect(row, cMin, false);
- aColumn = cm.getColumn(cMin);
- if (aColumn != draggedColumn) {
- columnWidth = aColumn.getWidth();
- cellRect.width = columnWidth - columnMargin;
- paintCell(g, cellRect, row, cMin);
- }
- for(int column = cMin+1; column <= cMax; column++) {
- aColumn = cm.getColumn(column);
- columnWidth = aColumn.getWidth();
- // TODO
- cellRect.width = columnWidth - columnMargin;
- cellRect.x -= columnWidth;
- if (aColumn != draggedColumn) {
- paintCell(g, cellRect, row, column);
- }
- }
- }
- }
- // Paint the dragged column if we are dragging.
- if (draggedColumn != null) {
- paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
- }
- // Remove any renderers that may be left in the rendererPane.
- rendererPane.removeAll();
- }
- private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
- if (table.isEditing() && table.getEditingRow()==row &&
- table.getEditingColumn()==column) {
- Component component = table.getEditorComponent();
- component.setBounds(cellRect);
- component.validate();
- }
- else {
- TableCellRenderer renderer = table.getCellRenderer(row, column);
- Component component = table.prepareRenderer(renderer, row, column);
- if( component instanceof JComponent ){
- ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
- }
- rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
- cellRect.width, cellRect.height, true);
- }
- }
- private Rectangle getHDropLineRect(JTable.DropLocation loc) {
- if (!loc.isInsertRow()) {
- return null;
- }
- int row = loc.getRow();
- int col = loc.getColumn();
- if (col >= table.getColumnCount()) {
- col--;
- }
- Rectangle rect = table.getCellRect(row, col, true);
- if (row >= table.getRowCount()) {
- row--;
- Rectangle prevRect = table.getCellRect(row, col, true);
- rect.y = prevRect.y + prevRect.height;
- }
- if (rect.y == 0) {
- rect.y = -1;
- } else {
- rect.y -= 2;
- }
- rect.height = 3;
- return rect;
- }
- private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
- int draggedColumnIndex = viewIndexForColumn(draggedColumn);
- Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
- Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
- Rectangle vacatedColumnRect = minCell.union(maxCell);
- // Paint a gray well in place of the moving column.
- g.setColor(table.getParent().getBackground());
- g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
- vacatedColumnRect.width, vacatedColumnRect.height);
- // Move to the where the cell has been dragged.
- vacatedColumnRect.x += distance;
- // Fill the background.
- g.setColor(table.getBackground());
- g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
- vacatedColumnRect.width, vacatedColumnRect.height);
- // Paint the vertical grid lines if necessary.
- if (table.getShowVerticalLines()) {
- g.setColor(table.getGridColor());
- int x1 = vacatedColumnRect.x;
- int y1 = vacatedColumnRect.y;
- int x2 = x1 + vacatedColumnRect.width - 1;
- int y2 = y1 + vacatedColumnRect.height - 1;
- // Left
- g.drawLine(x1-1, y1, x1-1, y2);
- // Right
- g.drawLine(x2, y1, x2, y2);
- }
- for(int row = rMin; row <= rMax; row++) {
- // Render the cell value
- Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
- r.x += distance;
- paintCell(g, r, row, draggedColumnIndex);
- // Paint the (lower) horizontal grid line if necessary.
- if (table.getShowHorizontalLines()) {
- g.setColor(table.getGridColor());
- Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
- rcr.x += distance;
- int x1 = rcr.x;
- int y1 = rcr.y;
- int x2 = x1 + rcr.width - 1;
- int y2 = y1 + rcr.height - 1;
- g.drawLine(x1, y2, x2, y2);
- }
- }
- }
- private int viewIndexForColumn(TableColumn aColumn) {
- TableColumnModel cm = table.getColumnModel();
- for (int column = 0; column < cm.getColumnCount(); column++) {
- if (cm.getColumn(column) == aColumn) {
- return column;
- }
- }
- return -1;
- }
- private Rectangle extendRect(Rectangle rect, boolean horizontal) {
- if (rect == null) {
- return rect;
- }
- if (horizontal) {
- rect.x = 0;
- rect.width = table.getWidth();
- } else {
- rect.y = 0;
- if (table.getRowCount() != 0) {
- Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
- rect.height = lastRect.y + lastRect.height;
- } else {
- rect.height = table.getHeight();
- }
- }
- return rect;
- }
- private Rectangle getVDropLineRect(JTable.DropLocation loc) {
- if (!loc.isInsertColumn()) {
- return null;
- }
- boolean ltr = table.getComponentOrientation().isLeftToRight();
- int col = loc.getColumn();
- Rectangle rect = table.getCellRect(loc.getRow(), col, true);
- if (col >= table.getColumnCount()) {
- col--;
- rect = table.getCellRect(loc.getRow(), col, true);
- if (ltr) {
- rect.x = rect.x + rect.width;
- }
- } else if (!ltr) {
- rect.x = rect.x + rect.width;
- }
- if (rect.x == 0) {
- rect.x = -1;
- } else {
- rect.x -= 2;
- }
- rect.width = 3;
- return rect;
- }
- } // End of Class BasicTableUI
package org.dxj.guitools.gridbagtable;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class GridBagTableUI extends BasicTableUI
{
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createTableSize(width);
}
private Dimension createTableSize(long width) {
int height = 0;
int rowCount = table.getRowCount();
if (rowCount > 0 && table.getColumnCount() > 0) {
Rectangle r = table.getCellRect(rowCount-1, 0, true);
height = r.y + r.height;
}
// Width is always positive. The call to abs() is a workaround for
// a bug in the 1.1.6 JIT on Windows.
long tmp = Math.abs(width);
if (tmp > Integer.MAX_VALUE) {
tmp = Integer.MAX_VALUE;
}
return new Dimension((int)tmp, height);
}
public void paint(Graphics g, JComponent c) {
Rectangle clip = g.getClipBounds();
Rectangle bounds = table.getBounds();
// account for the fact that the graphics has already been translated
// into the table's bounds
bounds.x = bounds.y = 0;
if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
// this check prevents us from painting the entire table
// when the clip doesn't intersect our bounds at all
!bounds.intersects(clip)) {
paintDropLines(g);
return;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
Point upperLeft = clip.getLocation();
if (!ltr) {
upperLeft.x++;
}
Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
clip.y + clip.height);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
// This should never happen (as long as our bounds intersect the clip,
// which is why we bail above if that is the case).
if (rMin == -1) {
rMin = 0;
}
// If the table does not have enough rows to fill the view we'll get -1.
// (We could also get -1 if our bounds don't intersect the clip,
// which is why we bail above if that is the case).
// Replace this with the index of the last row.
if (rMax == -1) {
rMax = table.getRowCount()-1;
}
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
if (cMin == -1) {
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if (cMax == -1) {
cMax = table.getColumnCount()-1;
}
// Paint the grid.
//paintGrid(g, rMin, rMax, cMin, cMax);
// Paint the cells.
paintCells(g, rMin, rMax, cMin, cMax);
paintDropLines(g);
}
private void paintDropLines(Graphics g) {
JTable.DropLocation loc = table.getDropLocation();
if (loc == null) {
return;
}
Color color = UIManager.getColor("Table.dropLineColor");
Color shortColor = UIManager.getColor("Table.dropLineShortColor");
if (color == null && shortColor == null) {
return;
}
Rectangle rect;
rect = getHDropLineRect(loc);
if (rect != null) {
int x = rect.x;
int w = rect.width;
if (color != null) {
extendRect(rect, true);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertColumn() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(x, rect.y, w, rect.height);
}
}
rect = getVDropLineRect(loc);
if (rect != null) {
int y = rect.y;
int h = rect.height;
if (color != null) {
extendRect(rect, false);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertRow() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(rect.x, y, rect.width, h);
}
}
}
/*
* Paints the grid lines within <I>aRect</I>, using the grid
* color set with <I>setGridColor</I>. Paints vertical lines
* if <code>getShowVerticalLines()</code> returns true and paints
* horizontal lines if <code>getShowHorizontalLines()</code>
* returns true.
*/
private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
g.setColor(table.getGridColor());
Rectangle minCell = table.getCellRect(rMin, cMin, true);
Rectangle maxCell = table.getCellRect(rMax, cMax, true);
Rectangle damagedArea = minCell.union( maxCell );
if (table.getShowHorizontalLines()) {
int tableWidth = damagedArea.x + damagedArea.width;
int y = damagedArea.y;
for (int row = rMin; row <= rMax; row++) {
y += table.getRowHeight(row);
g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
}
}
if (table.getShowVerticalLines()) {
TableColumnModel cm = table.getColumnModel();
int tableHeight = damagedArea.y + damagedArea.height;
int x;
if (table.getComponentOrientation().isLeftToRight()) {
x = damagedArea.x;
for (int column = cMin; column <= cMax; column++) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
} else {
x = damagedArea.x;
for (int column = cMax; column >= cMin; column--) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
}
}
}
private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
JTableHeader header = table.getTableHeader();
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
TableColumnModel cm = table.getColumnModel();
int columnMargin = cm.getColumnMargin();
Rectangle cellRect;
TableColumn aColumn;
int columnWidth;
if (table.getComponentOrientation().isLeftToRight()) {
for(int row = rMin; row <= rMax; row++) {
if( table instanceof GridBagTable )
cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
else
cellRect = table.getCellRect(row, cMin, false);
for(int column = cMin; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
//TODO
cellRect.width = columnWidth - columnMargin;
int oldHeight = cellRect.height;
if( table instanceof GridBagTable ){
if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
cellRect.width = 0;
cellRect.height = 0;
}
else{
int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
if( h >1 ){
for( int n=1; n<h; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
}
int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
if( v >1 ){
for( int n=1; n<v; n++)
cellRect.height += table.getRowHeight(row+n);
}
}
}
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
cellRect.height = oldHeight;
cellRect.x += columnWidth;
}
}
} else {
for(int row = rMin; row <= rMax; row++) {
cellRect = table.getCellRect(row, cMin, false);
aColumn = cm.getColumn(cMin);
if (aColumn != draggedColumn) {
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
paintCell(g, cellRect, row, cMin);
}
for(int column = cMin+1; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
// TODO
cellRect.width = columnWidth - columnMargin;
cellRect.x -= columnWidth;
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
}
}
}
// Paint the dragged column if we are dragging.
if (draggedColumn != null) {
paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
}
// Remove any renderers that may be left in the rendererPane.
rendererPane.removeAll();
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if( component instanceof JComponent ){
((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
}
private Rectangle getHDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertRow()) {
return null;
}
int row = loc.getRow();
int col = loc.getColumn();
if (col >= table.getColumnCount()) {
col--;
}
Rectangle rect = table.getCellRect(row, col, true);
if (row >= table.getRowCount()) {
row--;
Rectangle prevRect = table.getCellRect(row, col, true);
rect.y = prevRect.y + prevRect.height;
}
if (rect.y == 0) {
rect.y = -1;
} else {
rect.y -= 2;
}
rect.height = 3;
return rect;
}
private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
int draggedColumnIndex = viewIndexForColumn(draggedColumn);
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
Rectangle vacatedColumnRect = minCell.union(maxCell);
// Paint a gray well in place of the moving column.
g.setColor(table.getParent().getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Move to the where the cell has been dragged.
vacatedColumnRect.x += distance;
// Fill the background.
g.setColor(table.getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Paint the vertical grid lines if necessary.
if (table.getShowVerticalLines()) {
g.setColor(table.getGridColor());
int x1 = vacatedColumnRect.x;
int y1 = vacatedColumnRect.y;
int x2 = x1 + vacatedColumnRect.width - 1;
int y2 = y1 + vacatedColumnRect.height - 1;
// Left
g.drawLine(x1-1, y1, x1-1, y2);
// Right
g.drawLine(x2, y1, x2, y2);
}
for(int row = rMin; row <= rMax; row++) {
// Render the cell value
Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
r.x += distance;
paintCell(g, r, row, draggedColumnIndex);
// Paint the (lower) horizontal grid line if necessary.
if (table.getShowHorizontalLines()) {
g.setColor(table.getGridColor());
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
rcr.x += distance;
int x1 = rcr.x;
int y1 = rcr.y;
int x2 = x1 + rcr.width - 1;
int y2 = y1 + rcr.height - 1;
g.drawLine(x1, y2, x2, y2);
}
}
}
private int viewIndexForColumn(TableColumn aColumn) {
TableColumnModel cm = table.getColumnModel();
for (int column = 0; column < cm.getColumnCount(); column++) {
if (cm.getColumn(column) == aColumn) {
return column;
}
}
return -1;
}
private Rectangle extendRect(Rectangle rect, boolean horizontal) {
if (rect == null) {
return rect;
}
if (horizontal) {
rect.x = 0;
rect.width = table.getWidth();
} else {
rect.y = 0;
if (table.getRowCount() != 0) {
Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
rect.height = lastRect.y + lastRect.height;
} else {
rect.height = table.getHeight();
}
}
return rect;
}
private Rectangle getVDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertColumn()) {
return null;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
int col = loc.getColumn();
Rectangle rect = table.getCellRect(loc.getRow(), col, true);
if (col >= table.getColumnCount()) {
col--;
rect = table.getCellRect(loc.getRow(), col, true);
if (ltr) {
rect.x = rect.x + rect.width;
}
} else if (!ltr) {
rect.x = rect.x + rect.width;
}
if (rect.x == 0) {
rect.x = -1;
} else {
rect.x -= 2;
}
rect.width = 3;
return rect;
}
} // End of Class BasicTableUI
测试代码:
- import java.awt.BorderLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JScrollPane;
- import javax.swing.table.DefaultTableModel;
- import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- public class Test implements ActionListener{
- GridBagTable table;
- public Test()
- {
- JFrame d = new JFrame();
- DefaultTableModel model = new DefaultTableModel(5,5);
- table = new GridBagTable(model);
- table.setRowHeight(20);
- JScrollPane pane = new JScrollPane(table);
- d.getContentPane().add(pane, BorderLayout.CENTER);
- JButton btn = new JButton("合并/拆分");
- d.getContentPane().add(btn, BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0, 0, 400, 400);
- d.setVisible(true);
- }
- public static void main(String[] fsd){
- new Test();
- }
- public void actionPerformed(ActionEvent e) {
- table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());
- }
-
} 年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。
GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。- package org.dxj.guitools.gridbagtable;
- import java.awt.Component;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.util.Enumeration;
- import java.util.EventObject;
- import javax.swing.DefaultCellEditor;
- import javax.swing.JTable;
- import javax.swing.SwingUtilities;
- import javax.swing.event.TableModelEvent;
- import javax.swing.table.AbstractTableModel;
- import javax.swing.table.TableColumn;
- import javax.swing.table.TableColumnModel;
- /**
- * @author 15860102@qq.com
- */
- public class GridBagTable extends JTable{
- GridBagModel gridBagModel;
- public GridBagModel getGridBagModel() {
- return gridBagModel;
- }
- public void setGridBagModel(GridBagModel gridBagModel){
- if( gridBagModel != null && gridBagModel != this.gridBagModel )
- this.gridBagModel = gridBagModel;
- }
- public GridBagTable(AbstractTableModel dm){
- super(dm);
- getTableHeader().setReorderingAllowed(false);
- gridBagModel = new DefaultGridBagTableModel(dm);
- getColumnModel().setColumnSelectionAllowed(true);
- }
- private void updateSubComponentUI(Object componentShell) {
- if (componentShell == null) {
- return;
- }
- Component component = null;
- if (componentShell instanceof Component) {
- component = (Component)componentShell;
- }
- if (componentShell instanceof DefaultCellEditor) {
- component = ((DefaultCellEditor)componentShell).getComponent();
- }
- if (component != null) {
- SwingUtilities.updateComponentTreeUI(component);
- }
- }
- public void updateUI() {
- // Update the UIs of the cell renderers, cell editors and header renderers.
- TableColumnModel cm = getColumnModel();
- for(int column = 0; column < cm.getColumnCount(); column++) {
- TableColumn aColumn = cm.getColumn(column);
- updateSubComponentUI(aColumn.getCellRenderer());
- updateSubComponentUI(aColumn.getCellEditor());
- updateSubComponentUI(aColumn.getHeaderRenderer());
- }
- // Update the UIs of all the default renderers.
- Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
- while (defaultRenderers.hasMoreElements()) {
- updateSubComponentUI(defaultRenderers.nextElement());
- }
- // Update the UIs of all the default editors.
- Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
- while (defaultEditors.hasMoreElements()) {
- updateSubComponentUI(defaultEditors.nextElement());
- }
- // Update the UI of the table header
- if (tableHeader != null && tableHeader.getParent() == null) {
- tableHeader.updateUI();
- }
- setUI(new GridBagTableUI());
- }
- public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
- return super.getCellRect(row, column, includeSpacing);
- }
- public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
- Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
- int cols = gridBagModel.getColumnGrid(row, column);
- TableColumnModel cm = getColumnModel();
- for( int n=1; n<cols; n++)
- cellRect.width += cm.getColumn(column+n).getWidth();
- int rows = gridBagModel.getRowGrid(row, column);
- for( int n=1; n<rows; n++)
- cellRect.height += getRowHeight(row+n);
- return cellRect;
- }
- public void tableChanged(TableModelEvent e){
- super.tableChanged(e);
- //TODO
- }
- public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
- if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
- repaint();
- return true;
- }
- return false;
- }
- public boolean mergeCells(int[] rows, int[] columns){
- if( gridBagModel.mergeCells(rows, columns)){
- repaint();
- return true;
- }
- return false;
- }
- public boolean spliteCellAt(int row, int column){
- if( gridBagModel.spliteCellAt(row, column)){
- repaint();
- return true;
- }
- return false;
- }
- public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
- if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
- super.changeSelection(rowIndex, columnIndex, toggle, extend);
- Point p;
- for( int row = rowIndex; row >= 0; row-- ){
- for( int col = columnIndex; col >= 0; col-- ){
- p = gridBagModel.getGrid(row, col);
- //p = ((Point)((Vector)rowVector.get(row)).get(col));
- if( col + p.x > columnIndex && row + p.y > rowIndex){
- rowIndex = row;
- columnIndex = col;
- break;
- }
- }
- }
- super.changeSelection(rowIndex, columnIndex, toggle, extend);
- repaint();
- }
- public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
- if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
- return super.editCellAt(rowIndex, columnIndex, e);
- Point p;
- for( int row = rowIndex; row >= 0; row-- ){
- for( int col = columnIndex; col >= 0; col-- ){
- p = gridBagModel.getGrid(row, col);
- if( col + p.x > columnIndex && row + p.y > rowIndex){
- rowIndex = row;
- columnIndex = col;
- break;
- }
- }
- }
- return super.editCellAt(rowIndex, columnIndex, e);
- }
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* @author 15860102@qq.com
*/
public class GridBagTable extends JTable{
GridBagModel gridBagModel;
public GridBagModel getGridBagModel() {
return gridBagModel;
}
public void setGridBagModel(GridBagModel gridBagModel){
if( gridBagModel != null && gridBagModel != this.gridBagModel )
this.gridBagModel = gridBagModel;
}
public GridBagTable(AbstractTableModel dm){
super(dm);
getTableHeader().setReorderingAllowed(false);
gridBagModel = new DefaultGridBagTableModel(dm);
getColumnModel().setColumnSelectionAllowed(true);
}
private void updateSubComponentUI(Object componentShell) {
if (componentShell == null) {
return;
}
Component component = null;
if (componentShell instanceof Component) {
component = (Component)componentShell;
}
if (componentShell instanceof DefaultCellEditor) {
component = ((DefaultCellEditor)componentShell).getComponent();
}
if (component != null) {
SwingUtilities.updateComponentTreeUI(component);
}
}
public void updateUI() {
// Update the UIs of the cell renderers, cell editors and header renderers.
TableColumnModel cm = getColumnModel();
for(int column = 0; column < cm.getColumnCount(); column++) {
TableColumn aColumn = cm.getColumn(column);
updateSubComponentUI(aColumn.getCellRenderer());
updateSubComponentUI(aColumn.getCellEditor());
updateSubComponentUI(aColumn.getHeaderRenderer());
}
// Update the UIs of all the default renderers.
Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
while (defaultRenderers.hasMoreElements()) {
updateSubComponentUI(defaultRenderers.nextElement());
}
// Update the UIs of all the default editors.
Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
while (defaultEditors.hasMoreElements()) {
updateSubComponentUI(defaultEditors.nextElement());
}
// Update the UI of the table header
if (tableHeader != null && tableHeader.getParent() == null) {
tableHeader.updateUI();
}
setUI(new GridBagTableUI());
}
public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
return super.getCellRect(row, column, includeSpacing);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
int cols = gridBagModel.getColumnGrid(row, column);
TableColumnModel cm = getColumnModel();
for( int n=1; n<cols; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
int rows = gridBagModel.getRowGrid(row, column);
for( int n=1; n<rows; n++)
cellRect.height += getRowHeight(row+n);
return cellRect;
}
public void tableChanged(TableModelEvent e){
super.tableChanged(e);
//TODO
}
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
repaint();
return true;
}
return false;
}
public boolean mergeCells(int[] rows, int[] columns){
if( gridBagModel.mergeCells(rows, columns)){
repaint();
return true;
}
return false;
}
public boolean spliteCellAt(int row, int column){
if( gridBagModel.spliteCellAt(row, column)){
repaint();
return true;
}
return false;
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
super.changeSelection(rowIndex, columnIndex, toggle, extend);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
//p = ((Point)((Vector)rowVector.get(row)).get(col));
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
repaint();
}
public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED )
return super.editCellAt(rowIndex, columnIndex, e);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
return super.editCellAt(rowIndex, columnIndex, e);
}
}- package org.dxj.guitools.gridbagtable;
- import java.awt.Point;
- public interface GridBagModel {
- //格子处于正常状态
- int DEFAULT = 0;
- //格子合并了其他的格子
- int MERGE = 1;
- //格子被其他格子合并
- int COVERED = -1;
- /**
- * @param row 行
- * @param column 列
- * @return 该单元格在行、列的跨度
- */
- Point getGrid(int row, int column);
- /**
- * 在Y轴方向的跨度
- * @param row
- * @param column
- * @return
- */
- int getRowGrid(int row, int column);
- /**
- * 在X轴方向的跨度
- * @param row
- * @param column
- * @return
- */
- int getColumnGrid(int row, int column);
- /**
- * @param rows 行集合
- * @param columns 列集合
- * @return 单元格集合是否可以合并在一起
- */
- boolean canMergeCells(int[] rows, int[] columns);
- /**
- * 判断该单元格状态
- * @param row
- * @param column
- * @return MERGE|DEFAULT|COVERED
- */
- int getCellState(int row, int column);
- /**
- * 将单元格集合合并
- * @param startRow 开始行
- * @param endRow 结束行
- * @param startColumn 开始列
- * @param endColumn 结束列
- * @return 是否合并成功
- */
- boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
- /**
- * 将单元格集合合并
- * @param rows 行集合
- * @param columns 列集合
- * @return 是否合并成功
- */
- boolean mergeCells(int[] rows, int[] columns);
- /**
- * 拆分单元格
- * @param row 行
- * @param column 列
- * @return 是否拆分成功
- */
- boolean spliteCellAt(int row, int column);
- /**
- * 清除 所有合并
- */
- void clearMergence();
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
public interface GridBagModel {
//格子处于正常状态
int DEFAULT = 0;
//格子合并了其他的格子
int MERGE = 1;
//格子被其他格子合并
int COVERED = -1;
/**
* @param row 行
* @param column 列
* @return 该单元格在行、列的跨度
*/
Point getGrid(int row, int column);
/**
* 在Y轴方向的跨度
* @param row
* @param column
* @return
*/
int getRowGrid(int row, int column);
/**
* 在X轴方向的跨度
* @param row
* @param column
* @return
*/
int getColumnGrid(int row, int column);
/**
* @param rows 行集合
* @param columns 列集合
* @return 单元格集合是否可以合并在一起
*/
boolean canMergeCells(int[] rows, int[] columns);
/**
* 判断该单元格状态
* @param row
* @param column
* @return MERGE|DEFAULT|COVERED
*/
int getCellState(int row, int column);
/**
* 将单元格集合合并
* @param startRow 开始行
* @param endRow 结束行
* @param startColumn 开始列
* @param endColumn 结束列
* @return 是否合并成功
*/
boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
/**
* 将单元格集合合并
* @param rows 行集合
* @param columns 列集合
* @return 是否合并成功
*/
boolean mergeCells(int[] rows, int[] columns);
/**
* 拆分单元格
* @param row 行
* @param column 列
* @return 是否拆分成功
*/
boolean spliteCellAt(int row, int column);
/**
* 清除 所有合并
*/
void clearMergence();
}- package org.dxj.guitools.gridbagtable;
- import java.awt.Point;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Vector;
- import javax.swing.event.TableModelEvent;
- import javax.swing.event.TableModelListener;
- import javax.swing.table.AbstractTableModel;
- public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
- protected AbstractTableModel model;
- protected List<List<Point>> gridInfo;
- DefaultGridBagTableModel(AbstractTableModel model){
- gridInfo = new Vector<List<Point>>();
- setTableModel(model);
- }
- public void setTableModel(AbstractTableModel model){
- if( model != null && model != this.model ){
- if( this.model != null )
- this.model.removeTableModelListener(this);
- //防止多次添加监听器
- model.removeTableModelListener(this);
- model.addTableModelListener(this);
- this.model = model;
- clearMergence();
- }
- }
- public void clearMergence(){
- if( gridInfo == null )
- gridInfo = new Vector<List<Point>>();
- else
- gridInfo.clear();
- if( model == null )
- return;
- //初始化,每个格子占的格子数为(1,1);
- for(int row=model.getRowCount(); --row>=0;){
- List<Point> infos = new Vector<Point>();
- gridInfo.add(infos);
- for(int col=model.getColumnCount(); --col>=0;){
- infos.add(getDefaultPoint());
- }
- }
- }
- public Point getDefaultPoint(){
- return new Point(1,1);
- }
- @Override
- public boolean canMergeCells(int[] rows, int[] columns) {
- if( rows == null || columns == null ) return false;
- Arrays.sort(rows);
- for(int index=0; index<rows.length-1; index++){
- if( rows[index+1] - rows[index] > 1 )
- return false;
- }
- Arrays.sort(columns);
- for(int index=0; index<columns.length-1; index++){
- if( columns[index+1] - columns[index] > 1 )
- return false;
- }
- return true;
- }
- @Override
- public int getCellState(int row, int column) {
- Point grid = getGrid(row, column);
- if( grid == null ) return DEFAULT;
- if( grid.x>1 || grid.y>1 )
- return MERGE;
- if( grid.x<=0 || grid.y<=0 )
- return COVERED;
- return DEFAULT;
- }
- @Override
- public int getColumnGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null )
- return point.x;
- }
- }
- return 1;
- }
- @Override
- public Point getGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- return gridRow.get(column);
- }
- }
- return getDefaultPoint();
- }
- @Override
- public int getRowGrid(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null )
- return point.y;
- }
- }
- return 1;
- }
- protected boolean setGrid(int row, int column, Point grid) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null ){
- point.setLocation(grid);
- }
- else{
- gridRow.set(column, grid.getLocation());
- }
- return true;
- }
- }
- return false;
- }
- @Override
- public boolean spliteCellAt(int row, int column) {
- if( gridInfo != null && row >=0 && row < gridInfo.size() ){
- List<Point> gridRow = gridInfo.get(row);
- if( gridRow != null && column >=0 && column < gridRow.size() ){
- Point point = gridRow.get(column);
- if( point != null ){
- point = point.getLocation();
- for(int a=0; a<point.y; a++){
- for(int b=0; b<point.x; b++){
- setGrid(row+a, column+b, getDefaultPoint());
- }
- }
- }
- else{
- gridRow.set(column, getDefaultPoint());
- }
- return true;
- }
- }
- return false;
- }
- @Override
- /**
- * table中发生行的添加和删除的时候需要修改该模型
- */
- public void tableChanged(TableModelEvent e) {
- //TODO
- }
- @Override
- public boolean mergeCells(int[] rows, int[] columns) {
- if( !canMergeCells(rows, columns) )
- return false;
- Arrays.sort(rows);
- Arrays.sort(columns);
- return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
- }
- @Override
- public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
- setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
- for(int row=startRow; row<=endRow; row++){
- for(int col=startColumn; col<=endColumn; col++){
- if(row==startRow&&col==startColumn)
- continue;
- else
- setGrid(row, col, new Point(COVERED,COVERED));
- }
- }
- return true;
- }
- public String toString(){
- if( gridInfo == null )
- return "";
- StringBuffer sb = new StringBuffer();
- for(List<Point> rowInfo : gridInfo ){
- for(Point grid : rowInfo){
- sb.append("["+grid.x+","+grid.y+"], ");
- }
- sb.append("\n");
- }
- return sb.toString();
- }
- }
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
protected AbstractTableModel model;
protected List<List<Point>> gridInfo;
DefaultGridBagTableModel(AbstractTableModel model){
gridInfo = new Vector<List<Point>>();
setTableModel(model);
}
public void setTableModel(AbstractTableModel model){
if( model != null && model != this.model ){
if( this.model != null )
this.model.removeTableModelListener(this);
//防止多次添加监听器
model.removeTableModelListener(this);
model.addTableModelListener(this);
this.model = model;
clearMergence();
}
}
public void clearMergence(){
if( gridInfo == null )
gridInfo = new Vector<List<Point>>();
else
gridInfo.clear();
if( model == null )
return;
//初始化,每个格子占的格子数为(1,1);
for(int row=model.getRowCount(); --row>=0;){
List<Point> infos = new Vector<Point>();
gridInfo.add(infos);
for(int col=model.getColumnCount(); --col>=0;){
infos.add(getDefaultPoint());
}
}
}
public Point getDefaultPoint(){
return new Point(1,1);
}
@Override
public boolean canMergeCells(int[] rows, int[] columns) {
if( rows == null || columns == null ) return false;
Arrays.sort(rows);
for(int index=0; index<rows.length-1; index++){
if( rows[index+1] - rows[index] > 1 )
return false;
}
Arrays.sort(columns);
for(int index=0; index<columns.length-1; index++){
if( columns[index+1] - columns[index] > 1 )
return false;
}
return true;
}
@Override
public int getCellState(int row, int column) {
Point grid = getGrid(row, column);
if( grid == null ) return DEFAULT;
if( grid.x>1 || grid.y>1 )
return MERGE;
if( grid.x<=0 || grid.y<=0 )
return COVERED;
return DEFAULT;
}
@Override
public int getColumnGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.x;
}
}
return 1;
}
@Override
public Point getGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
return gridRow.get(column);
}
}
return getDefaultPoint();
}
@Override
public int getRowGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.y;
}
}
return 1;
}
protected boolean setGrid(int row, int column, Point grid) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point.setLocation(grid);
}
else{
gridRow.set(column, grid.getLocation());
}
return true;
}
}
return false;
}
@Override
public boolean spliteCellAt(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point = point.getLocation();
for(int a=0; a<point.y; a++){
for(int b=0; b<point.x; b++){
setGrid(row+a, column+b, getDefaultPoint());
}
}
}
else{
gridRow.set(column, getDefaultPoint());
}
return true;
}
}
return false;
}
@Override
/**
* table中发生行的添加和删除的时候需要修改该模型
*/
public void tableChanged(TableModelEvent e) {
//TODO
}
@Override
public boolean mergeCells(int[] rows, int[] columns) {
if( !canMergeCells(rows, columns) )
return false;
Arrays.sort(rows);
Arrays.sort(columns);
return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
}
@Override
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
for(int row=startRow; row<=endRow; row++){
for(int col=startColumn; col<=endColumn; col++){
if(row==startRow&&col==startColumn)
continue;
else
setGrid(row, col, new Point(COVERED,COVERED));
}
}
return true;
}
public String toString(){
if( gridInfo == null )
return "";
StringBuffer sb = new StringBuffer();
for(List<Point> rowInfo : gridInfo ){
for(Point grid : rowInfo){
sb.append("["+grid.x+","+grid.y+"], ");
}
sb.append("\n");
}
return sb.toString();
}
}- package org.dxj.guitools.gridbagtable;
- import java.awt.Color;
- import java.awt.Component;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.util.Enumeration;
- import javax.swing.BorderFactory;
- import javax.swing.JComponent;
- import javax.swing.JTable;
- import javax.swing.UIManager;
- import javax.swing.plaf.basic.BasicTableUI;
- import javax.swing.table.JTableHeader;
- import javax.swing.table.TableCellRenderer;
- import javax.swing.table.TableColumn;
- import javax.swing.table.TableColumnModel;
- public class GridBagTableUI extends BasicTableUI
- {
- public Dimension getPreferredSize(JComponent c) {
- long width = 0;
- Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
- while (enumeration.hasMoreElements()) {
- TableColumn aColumn = (TableColumn)enumeration.nextElement();
- width = width + aColumn.getPreferredWidth();
- }
- return createTableSize(width);
- }
- private Dimension createTableSize(long width) {
- int height = 0;
- int rowCount = table.getRowCount();
- if (rowCount > 0 && table.getColumnCount() > 0) {
- Rectangle r = table.getCellRect(rowCount-1, 0, true);
- height = r.y + r.height;
- }
- // Width is always positive. The call to abs() is a workaround for
- // a bug in the 1.1.6 JIT on Windows.
- long tmp = Math.abs(width);
- if (tmp > Integer.MAX_VALUE) {
- tmp = Integer.MAX_VALUE;
- }
- return new Dimension((int)tmp, height);
- }
- public void paint(Graphics g, JComponent c) {
- Rectangle clip = g.getClipBounds();
- Rectangle bounds = table.getBounds();
- // account for the fact that the graphics has already been translated
- // into the table's bounds
- bounds.x = bounds.y = 0;
- if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
- // this check prevents us from painting the entire table
- // when the clip doesn't intersect our bounds at all
- !bounds.intersects(clip)) {
- paintDropLines(g);
- return;
- }
- boolean ltr = table.getComponentOrientation().isLeftToRight();
- Point upperLeft = clip.getLocation();
- if (!ltr) {
- upperLeft.x++;
- }
- Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
- clip.y + clip.height);
- int rMin = table.rowAtPoint(upperLeft);
- int rMax = table.rowAtPoint(lowerRight);
- // This should never happen (as long as our bounds intersect the clip,
- // which is why we bail above if that is the case).
- if (rMin == -1) {
- rMin = 0;
- }
- // If the table does not have enough rows to fill the view we'll get -1.
- // (We could also get -1 if our bounds don't intersect the clip,
- // which is why we bail above if that is the case).
- // Replace this with the index of the last row.
- if (rMax == -1) {
- rMax = table.getRowCount()-1;
- }
- int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
- int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
- // This should never happen.
- if (cMin == -1) {
- cMin = 0;
- }
- // If the table does not have enough columns to fill the view we'll get -1.
- // Replace this with the index of the last column.
- if (cMax == -1) {
- cMax = table.getColumnCount()-1;
- }
- // Paint the grid.
- //paintGrid(g, rMin, rMax, cMin, cMax);
- // Paint the cells.
- paintCells(g, rMin, rMax, cMin, cMax);
- paintDropLines(g);
- }
- private void paintDropLines(Graphics g) {
- JTable.DropLocation loc = table.getDropLocation();
- if (loc == null) {
- return;
- }
- Color color = UIManager.getColor("Table.dropLineColor");
- Color shortColor = UIManager.getColor("Table.dropLineShortColor");
- if (color == null && shortColor == null) {
- return;
- }
- Rectangle rect;
- rect = getHDropLineRect(loc);
- if (rect != null) {
- int x = rect.x;
- int w = rect.width;
- if (color != null) {
- extendRect(rect, true);
- g.setColor(color);
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- }
- if (!loc.isInsertColumn() && shortColor != null) {
- g.setColor(shortColor);
- g.fillRect(x, rect.y, w, rect.height);
- }
- }
- rect = getVDropLineRect(loc);
- if (rect != null) {
- int y = rect.y;
- int h = rect.height;
- if (color != null) {
- extendRect(rect, false);
- g.setColor(color);
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- }
- if (!loc.isInsertRow() && shortColor != null) {
- g.setColor(shortColor);
- g.fillRect(rect.x, y, rect.width, h);
- }
- }
- }
- /*
- * Paints the grid lines within <I>aRect</I>, using the grid
- * color set with <I>setGridColor</I>. Paints vertical lines
- * if <code>getShowVerticalLines()</code> returns true and paints
- * horizontal lines if <code>getShowHorizontalLines()</code>
- * returns true.
- */
- private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
- g.setColor(table.getGridColor());
- Rectangle minCell = table.getCellRect(rMin, cMin, true);
- Rectangle maxCell = table.getCellRect(rMax, cMax, true);
- Rectangle damagedArea = minCell.union( maxCell );
- if (table.getShowHorizontalLines()) {
- int tableWidth = damagedArea.x + damagedArea.width;
- int y = damagedArea.y;
- for (int row = rMin; row <= rMax; row++) {
- y += table.getRowHeight(row);
- g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
- }
- }
- if (table.getShowVerticalLines()) {
- TableColumnModel cm = table.getColumnModel();
- int tableHeight = damagedArea.y + damagedArea.height;
- int x;
- if (table.getComponentOrientation().isLeftToRight()) {
- x = damagedArea.x;
- for (int column = cMin; column <= cMax; column++) {
- int w = cm.getColumn(column).getWidth();
- x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
- }
- } else {
- x = damagedArea.x;
- for (int column = cMax; column >= cMin; column--) {
- int w = cm.getColumn(column).getWidth();
- x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
- }
- }
- }
- }
- private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
- JTableHeader header = table.getTableHeader();
- TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
- TableColumnModel cm = table.getColumnModel();
- int columnMargin = cm.getColumnMargin();
- Rectangle cellRect;
- TableColumn aColumn;
- int columnWidth;
- if (table.getComponentOrientation().isLeftToRight()) {
- for(int row = rMin; row <= rMax; row++) {
- if( table instanceof GridBagTable )
- cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
- else
- cellRect = table.getCellRect(row, cMin, false);
- for(int column = cMin; column <= cMax; column++) {
- aColumn = cm.getColumn(column);
- columnWidth = aColumn.getWidth();
- //TODO
- cellRect.width = columnWidth - columnMargin;
- int oldHeight = cellRect.height;
- if( table instanceof GridBagTable ){
- if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
- cellRect.width = 0;
- cellRect.height = 0;
- }
- else{
- int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
- if( h >1 ){
- for( int n=1; n<h; n++)
- cellRect.width += cm.getColumn(column+n).getWidth();
- }
- int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
- if( v >1 ){
- for( int n=1; n<v; n++)
- cellRect.height += table.getRowHeight(row+n);
- }
- }
- }
- if (aColumn != draggedColumn) {
- paintCell(g, cellRect, row, column);
- }
- cellRect.height = oldHeight;
- cellRect.x += columnWidth;
- }
- }
- } else {
- for(int row = rMin; row <= rMax; row++) {
- cellRect = table.getCellRect(row, cMin, false);
- aColumn = cm.getColumn(cMin);
- if (aColumn != draggedColumn) {
- columnWidth = aColumn.getWidth();
- cellRect.width = columnWidth - columnMargin;
- paintCell(g, cellRect, row, cMin);
- }
- for(int column = cMin+1; column <= cMax; column++) {
- aColumn = cm.getColumn(column);
- columnWidth = aColumn.getWidth();
- // TODO
- cellRect.width = columnWidth - columnMargin;
- cellRect.x -= columnWidth;
- if (aColumn != draggedColumn) {
- paintCell(g, cellRect, row, column);
- }
- }
- }
- }
- // Paint the dragged column if we are dragging.
- if (draggedColumn != null) {
- paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
- }
- // Remove any renderers that may be left in the rendererPane.
- rendererPane.removeAll();
- }
- private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
- if (table.isEditing() && table.getEditingRow()==row &&
- table.getEditingColumn()==column) {
- Component component = table.getEditorComponent();
- component.setBounds(cellRect);
- component.validate();
- }
- else {
- TableCellRenderer renderer = table.getCellRenderer(row, column);
- Component component = table.prepareRenderer(renderer, row, column);
- if( component instanceof JComponent ){
- ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
- }
- rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
- cellRect.width, cellRect.height, true);
- }
- }
- private Rectangle getHDropLineRect(JTable.DropLocation loc) {
- if (!loc.isInsertRow()) {
- return null;
- }
- int row = loc.getRow();
- int col = loc.getColumn();
- if (col >= table.getColumnCount()) {
- col--;
- }
- Rectangle rect = table.getCellRect(row, col, true);
- if (row >= table.getRowCount()) {
- row--;
- Rectangle prevRect = table.getCellRect(row, col, true);
- rect.y = prevRect.y + prevRect.height;
- }
- if (rect.y == 0) {
- rect.y = -1;
- } else {
- rect.y -= 2;
- }
- rect.height = 3;
- return rect;
- }
- private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
- int draggedColumnIndex = viewIndexForColumn(draggedColumn);
- Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
- Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
- Rectangle vacatedColumnRect = minCell.union(maxCell);
- // Paint a gray well in place of the moving column.
- g.setColor(table.getParent().getBackground());
- g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
- vacatedColumnRect.width, vacatedColumnRect.height);
- // Move to the where the cell has been dragged.
- vacatedColumnRect.x += distance;
- // Fill the background.
- g.setColor(table.getBackground());
- g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
- vacatedColumnRect.width, vacatedColumnRect.height);
- // Paint the vertical grid lines if necessary.
- if (table.getShowVerticalLines()) {
- g.setColor(table.getGridColor());
- int x1 = vacatedColumnRect.x;
- int y1 = vacatedColumnRect.y;
- int x2 = x1 + vacatedColumnRect.width - 1;
- int y2 = y1 + vacatedColumnRect.height - 1;
- // Left
- g.drawLine(x1-1, y1, x1-1, y2);
- // Right
- g.drawLine(x2, y1, x2, y2);
- }
- for(int row = rMin; row <= rMax; row++) {
- // Render the cell value
- Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
- r.x += distance;
- paintCell(g, r, row, draggedColumnIndex);
- // Paint the (lower) horizontal grid line if necessary.
- if (table.getShowHorizontalLines()) {
- g.setColor(table.getGridColor());
- Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
- rcr.x += distance;
- int x1 = rcr.x;
- int y1 = rcr.y;
- int x2 = x1 + rcr.width - 1;
- int y2 = y1 + rcr.height - 1;
- g.drawLine(x1, y2, x2, y2);
- }
- }
- }
- private int viewIndexForColumn(TableColumn aColumn) {
- TableColumnModel cm = table.getColumnModel();
- for (int column = 0; column < cm.getColumnCount(); column++) {
- if (cm.getColumn(column) == aColumn) {
- return column;
- }
- }
- return -1;
- }
- private Rectangle extendRect(Rectangle rect, boolean horizontal) {
- if (rect == null) {
- return rect;
- }
- if (horizontal) {
- rect.x = 0;
- rect.width = table.getWidth();
- } else {
- rect.y = 0;
- if (table.getRowCount() != 0) {
- Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
- rect.height = lastRect.y + lastRect.height;
- } else {
- rect.height = table.getHeight();
- }
- }
- return rect;
- }
- private Rectangle getVDropLineRect(JTable.DropLocation loc) {
- if (!loc.isInsertColumn()) {
- return null;
- }
- boolean ltr = table.getComponentOrientation().isLeftToRight();
- int col = loc.getColumn();
- Rectangle rect = table.getCellRect(loc.getRow(), col, true);
- if (col >= table.getColumnCount()) {
- col--;
- rect = table.getCellRect(loc.getRow(), col, true);
- if (ltr) {
- rect.x = rect.x + rect.width;
- }
- } else if (!ltr) {
- rect.x = rect.x + rect.width;
- }
- if (rect.x == 0) {
- rect.x = -1;
- } else {
- rect.x -= 2;
- }
- rect.width = 3;
- return rect;
- }
- } // End of Class BasicTableUI
package org.dxj.guitools.gridbagtable;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class GridBagTableUI extends BasicTableUI
{
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createTableSize(width);
}
private Dimension createTableSize(long width) {
int height = 0;
int rowCount = table.getRowCount();
if (rowCount > 0 && table.getColumnCount() > 0) {
Rectangle r = table.getCellRect(rowCount-1, 0, true);
height = r.y + r.height;
}
// Width is always positive. The call to abs() is a workaround for
// a bug in the 1.1.6 JIT on Windows.
long tmp = Math.abs(width);
if (tmp > Integer.MAX_VALUE) {
tmp = Integer.MAX_VALUE;
}
return new Dimension((int)tmp, height);
}
public void paint(Graphics g, JComponent c) {
Rectangle clip = g.getClipBounds();
Rectangle bounds = table.getBounds();
// account for the fact that the graphics has already been translated
// into the table's bounds
bounds.x = bounds.y = 0;
if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
// this check prevents us from painting the entire table
// when the clip doesn't intersect our bounds at all
!bounds.intersects(clip)) {
paintDropLines(g);
return;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
Point upperLeft = clip.getLocation();
if (!ltr) {
upperLeft.x++;
}
Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
clip.y + clip.height);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
// This should never happen (as long as our bounds intersect the clip,
// which is why we bail above if that is the case).
if (rMin == -1) {
rMin = 0;
}
// If the table does not have enough rows to fill the view we'll get -1.
// (We could also get -1 if our bounds don't intersect the clip,
// which is why we bail above if that is the case).
// Replace this with the index of the last row.
if (rMax == -1) {
rMax = table.getRowCount()-1;
}
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
if (cMin == -1) {
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if (cMax == -1) {
cMax = table.getColumnCount()-1;
}
// Paint the grid.
//paintGrid(g, rMin, rMax, cMin, cMax);
// Paint the cells.
paintCells(g, rMin, rMax, cMin, cMax);
paintDropLines(g);
}
private void paintDropLines(Graphics g) {
JTable.DropLocation loc = table.getDropLocation();
if (loc == null) {
return;
}
Color color = UIManager.getColor("Table.dropLineColor");
Color shortColor = UIManager.getColor("Table.dropLineShortColor");
if (color == null && shortColor == null) {
return;
}
Rectangle rect;
rect = getHDropLineRect(loc);
if (rect != null) {
int x = rect.x;
int w = rect.width;
if (color != null) {
extendRect(rect, true);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertColumn() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(x, rect.y, w, rect.height);
}
}
rect = getVDropLineRect(loc);
if (rect != null) {
int y = rect.y;
int h = rect.height;
if (color != null) {
extendRect(rect, false);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertRow() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(rect.x, y, rect.width, h);
}
}
}
/*
* Paints the grid lines within <I>aRect</I>, using the grid
* color set with <I>setGridColor</I>. Paints vertical lines
* if <code>getShowVerticalLines()</code> returns true and paints
* horizontal lines if <code>getShowHorizontalLines()</code>
* returns true.
*/
private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
g.setColor(table.getGridColor());
Rectangle minCell = table.getCellRect(rMin, cMin, true);
Rectangle maxCell = table.getCellRect(rMax, cMax, true);
Rectangle damagedArea = minCell.union( maxCell );
if (table.getShowHorizontalLines()) {
int tableWidth = damagedArea.x + damagedArea.width;
int y = damagedArea.y;
for (int row = rMin; row <= rMax; row++) {
y += table.getRowHeight(row);
g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
}
}
if (table.getShowVerticalLines()) {
TableColumnModel cm = table.getColumnModel();
int tableHeight = damagedArea.y + damagedArea.height;
int x;
if (table.getComponentOrientation().isLeftToRight()) {
x = damagedArea.x;
for (int column = cMin; column <= cMax; column++) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
} else {
x = damagedArea.x;
for (int column = cMax; column >= cMin; column--) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
}
}
}
private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
JTableHeader header = table.getTableHeader();
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
TableColumnModel cm = table.getColumnModel();
int columnMargin = cm.getColumnMargin();
Rectangle cellRect;
TableColumn aColumn;
int columnWidth;
if (table.getComponentOrientation().isLeftToRight()) {
for(int row = rMin; row <= rMax; row++) {
if( table instanceof GridBagTable )
cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
else
cellRect = table.getCellRect(row, cMin, false);
for(int column = cMin; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
//TODO
cellRect.width = columnWidth - columnMargin;
int oldHeight = cellRect.height;
if( table instanceof GridBagTable ){
if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
cellRect.width = 0;
cellRect.height = 0;
}
else{
int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
if( h >1 ){
for( int n=1; n<h; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
}
int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
if( v >1 ){
for( int n=1; n<v; n++)
cellRect.height += table.getRowHeight(row+n);
}
}
}
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
cellRect.height = oldHeight;
cellRect.x += columnWidth;
}
}
} else {
for(int row = rMin; row <= rMax; row++) {
cellRect = table.getCellRect(row, cMin, false);
aColumn = cm.getColumn(cMin);
if (aColumn != draggedColumn) {
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
paintCell(g, cellRect, row, cMin);
}
for(int column = cMin+1; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
// TODO
cellRect.width = columnWidth - columnMargin;
cellRect.x -= columnWidth;
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
}
}
}
// Paint the dragged column if we are dragging.
if (draggedColumn != null) {
paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
}
// Remove any renderers that may be left in the rendererPane.
rendererPane.removeAll();
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if( component instanceof JComponent ){
((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
}
private Rectangle getHDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertRow()) {
return null;
}
int row = loc.getRow();
int col = loc.getColumn();
if (col >= table.getColumnCount()) {
col--;
}
Rectangle rect = table.getCellRect(row, col, true);
if (row >= table.getRowCount()) {
row--;
Rectangle prevRect = table.getCellRect(row, col, true);
rect.y = prevRect.y + prevRect.height;
}
if (rect.y == 0) {
rect.y = -1;
} else {
rect.y -= 2;
}
rect.height = 3;
return rect;
}
private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
int draggedColumnIndex = viewIndexForColumn(draggedColumn);
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
Rectangle vacatedColumnRect = minCell.union(maxCell);
// Paint a gray well in place of the moving column.
g.setColor(table.getParent().getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Move to the where the cell has been dragged.
vacatedColumnRect.x += distance;
// Fill the background.
g.setColor(table.getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Paint the vertical grid lines if necessary.
if (table.getShowVerticalLines()) {
g.setColor(table.getGridColor());
int x1 = vacatedColumnRect.x;
int y1 = vacatedColumnRect.y;
int x2 = x1 + vacatedColumnRect.width - 1;
int y2 = y1 + vacatedColumnRect.height - 1;
// Left
g.drawLine(x1-1, y1, x1-1, y2);
// Right
g.drawLine(x2, y1, x2, y2);
}
for(int row = rMin; row <= rMax; row++) {
// Render the cell value
Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
r.x += distance;
paintCell(g, r, row, draggedColumnIndex);
// Paint the (lower) horizontal grid line if necessary.
if (table.getShowHorizontalLines()) {
g.setColor(table.getGridColor());
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
rcr.x += distance;
int x1 = rcr.x;
int y1 = rcr.y;
int x2 = x1 + rcr.width - 1;
int y2 = y1 + rcr.height - 1;
g.drawLine(x1, y2, x2, y2);
}
}
}
private int viewIndexForColumn(TableColumn aColumn) {
TableColumnModel cm = table.getColumnModel();
for (int column = 0; column < cm.getColumnCount(); column++) {
if (cm.getColumn(column) == aColumn) {
return column;
}
}
return -1;
}
private Rectangle extendRect(Rectangle rect, boolean horizontal) {
if (rect == null) {
return rect;
}
if (horizontal) {
rect.x = 0;
rect.width = table.getWidth();
} else {
rect.y = 0;
if (table.getRowCount() != 0) {
Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
rect.height = lastRect.y + lastRect.height;
} else {
rect.height = table.getHeight();
}
}
return rect;
}
private Rectangle getVDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertColumn()) {
return null;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
int col = loc.getColumn();
Rectangle rect = table.getCellRect(loc.getRow(), col, true);
if (col >= table.getColumnCount()) {
col--;
rect = table.getCellRect(loc.getRow(), col, true);
if (ltr) {
rect.x = rect.x + rect.width;
}
} else if (!ltr) {
rect.x = rect.x + rect.width;
}
if (rect.x == 0) {
rect.x = -1;
} else {
rect.x -= 2;
}
rect.width = 3;
return rect;
}
} // End of Class BasicTableUI测试代码:
- import java.awt.BorderLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JScrollPane;
- import javax.swing.table.DefaultTableModel;
- import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- public class Test implements ActionListener{
- GridBagTable table;
- public Test()
- {
- JFrame d = new JFrame();
- DefaultTableModel model = new DefaultTableModel(5,5);
- table = new GridBagTable(model);
- table.setRowHeight(20);
- JScrollPane pane = new JScrollPane(table);
- d.getContentPane().add(pane, BorderLayout.CENTER);
- JButton btn = new JButton("合并/拆分");
- d.getContentPane().add(btn, BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0, 0, 400, 400);
- d.setVisible(true);
- }
- public static void main(String[] fsd){
- new Test();
- }
- public void actionPerformed(ActionEvent e) {
- table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());
- }
- }