package org.openswing.swing.pivottable.cellspantable.client; import java.util.*; import java.awt.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.plaf.basic.*; import javax.swing.event.*; /** * <p>Title: OpenSwing Framework</p> * <p>Description: JTable with support for cells span.</p> * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p> * * <p> This file is part of OpenSwing Framework. * This library is free software; you can redistribute it and/or * modify it under the terms of the (LGPL) Lesser General Public * License as published by the Free Software Foundation; * * GNU LESSER GENERAL PUBLIC LICENSE * Version 2.1, February 1999 * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author may be contacted at: * maurocarniel@tin.it</p> * * @author Mauro Carniel * @version 1.0 */ public class CellSpanTable extends JTable { public CellSpanTable() { setShowGrid(false); this.getColumnModel().setColumnMargin(0); this.setRowMargin(0); // setUI(new CellSpanTableUI()); // getTableHeader().setReorderingAllowed(false); // setCellSelectionEnabled(true); // setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); } public void setModel(TableModel model) { super.setModel(model); setUI(new CellSpanTableUI()); // setShowGrid(false); // setGridSize(new Dimension(model.getColumnCount(),model.getRowCount())); } public Rectangle getCellRect(int row, int column, boolean includeSpacing) { Rectangle sRect = super.getCellRect(row,column,includeSpacing); if ((row <0) || (column<0) || (getRowCount() <= row) || (getColumnCount() <= column)) { return sRect; } if (!isGridVisible(row,column)) { int temp_row = row; int temp_column = column; row += getSpan(temp_row,temp_column)[ROW]; column += getSpan(temp_row,temp_column)[COLUMN]; } int[] n = getSpan(row,column); int index = 0; int columnMargin = getColumnModel().getColumnMargin(); Rectangle cellFrame = new Rectangle(); int aCellHeight = rowHeight + rowMargin; cellFrame.y = row * aCellHeight; cellFrame.height = n[ROW] * aCellHeight; Enumeration enumeration = getColumnModel().getColumns(); while (enumeration.hasMoreElements()) { TableColumn aColumn = (TableColumn)enumeration.nextElement(); cellFrame.width = aColumn.getWidth() + columnMargin; if (index == column) break; cellFrame.x += cellFrame.width; index++; } try { for (int i = 0; i < n[COLUMN] - 1; i++) { TableColumn aColumn = (TableColumn) enumeration.nextElement(); cellFrame.width += aColumn.getWidth() + columnMargin; } } catch (Exception ex) { } if (!includeSpacing) { Dimension spacing = getIntercellSpacing(); cellFrame.setBounds(cellFrame.x + spacing.width/2, cellFrame.y + spacing.height/2, cellFrame.width - spacing.width, cellFrame.height - spacing.height); } return cellFrame; } private int[] rowColumnAtPoint(Point point) { int[] retValue = {-1,-1}; int row = point.y / (rowHeight + rowMargin); if ((row <0)||(getRowCount() <= row)) return retValue; int column = getColumnModel().getColumnIndexAtX(point.x); if (isGridVisible(row,column)) { retValue[COLUMN] = column; retValue[ROW ] = row; return retValue; } retValue[COLUMN] = column + getSpan(row,column)[COLUMN]; retValue[ROW ] = row + getSpan(row,column)[ROW]; return retValue; } public int rowAtPoint(Point point) { return rowColumnAtPoint(point)[ROW]; } public int columnAtPoint(Point point) { return rowColumnAtPoint(point)[COLUMN]; } public void columnSelectionChanged(ListSelectionEvent e) { repaint(); } public void valueChanged(ListSelectionEvent e) { int firstIndex = e.getFirstIndex(); int lastIndex = e.getLastIndex(); if (firstIndex == -1 && lastIndex == -1) { // Selection cleared. repaint(); } Rectangle dirtyRegion = getCellRect(firstIndex, 0, false); int numCoumns = getColumnCount(); int index = firstIndex; for (int i=0;i<numCoumns;i++) { dirtyRegion.add(getCellRect(index, i, false)); } index = lastIndex; for (int i=0;i<numCoumns;i++) { dirtyRegion.add(getCellRect(index, i, false)); } repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height); } public static final int ROW = 0; public static final int COLUMN = 1; protected int rowSize; protected int columnSize; protected int[][][] span; protected void initValue() { for(int i=0; i<span.length;i++) { for(int j=0; j<span[i].length; j++) { span[i][j][COLUMN] = 1; span[i][j][ROW] = 1; } } } // // CellSpan // public int[] getSpan(int row, int column) { if (isOutOfBounds(row, column)) { int[] ret_code = {1,1}; return ret_code; } return span[row][column]; } public void setSpan(int[] span, int row, int column) { if (isOutOfBounds(row, column)) return; this.span[row][column] = span; } public boolean isGridVisible(int row, int column) { if (isOutOfBounds(row, column)) return false; if ((span[row][column][COLUMN] < 1) ||(span[row][column][ROW] < 1)) return false; return true; } public void combine(int[] rows, int[] columns) { if (isOutOfBounds(rows, columns)) return; int rowSpan = rows.length; int columnSpan = columns.length; int startRow = rows.length==0?0:rows[0]; int startColumn = columns.length==0?0:columns[0]; for (int i=0;i<rowSpan;i++) { for (int j=0;j<columnSpan;j++) { if ((span[startRow +i][startColumn +j][COLUMN] != 1) ||(span[startRow +i][startColumn +j][ROW] != 1)) { return ; } } } for (int i=0,ii=0;i<rowSpan;i++,ii--) { for (int j=0,jj=0;j<columnSpan;j++,jj--) { span[startRow +i][startColumn +j][COLUMN] = jj; span[startRow +i][startColumn +j][ROW] = ii; //System.out.println("r " +ii +" c " +jj); } } span[startRow][startColumn][COLUMN] = columnSpan; span[startRow][startColumn][ROW] = rowSpan; } public void split(int row, int column) { if (isOutOfBounds(row, column)) return; int columnSpan = span[row][column][COLUMN]; int rowSpan = span[row][column][ROW]; for (int i=0;i<rowSpan;i++) { for (int j=0;j<columnSpan;j++) { span[row +i][column +j][COLUMN] = 1; span[row +i][column +j][ROW] = 1; } } } public void addColumn() { int[][][] oldSpan = span; int numRows = oldSpan.length; int numColumns = oldSpan[0].length==0?0:oldSpan[0].length; span = new int[numRows][numColumns + 1][2]; for(int i=0;i<numRows;i++) { span[i] = new int[numColumns + 1][2]; System.arraycopy(oldSpan[i],0,span[i],0,oldSpan[i].length); span[i][numColumns][COLUMN] = 1; span[i][numColumns][ROW] = 1; } columnSize++; } public void addRow() { int[][][] oldSpan = span; int numRows = oldSpan.length; int numColumns = oldSpan.length==0?getModel().getColumnCount():oldSpan[0].length; span = new int[numRows + 1][numColumns][2]; System.arraycopy(oldSpan,0,span,0,numRows); for (int i=0;i<numColumns;i++) { span[numRows][i][COLUMN] = 1; span[numRows][i][ROW] = 1; } rowSize++; } public void insertRow(int row) { int[][][] oldSpan = span; int numRows = oldSpan.length; int numColumns = oldSpan.length==0?getModel().getColumnCount():oldSpan[0].length; span = new int[numRows + 1][numColumns][2]; if (0 < row) { System.arraycopy(oldSpan,0,span,0,row-1); } System.arraycopy(oldSpan,0,span,row,numRows - row); for (int i=0;i<numColumns;i++) { span[row][i][COLUMN] = 1; span[row][i][ROW] = 1; } rowSize++; } public void setGridSize(Dimension size) { columnSize = size.width; rowSize = size.height; span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW initValue(); } public final boolean isOutOfBounds(int row, int column) { if ((row < 0)||(rowSize <= row) ||(column < 0)||(columnSize <= column)) { return true; } return false; } public final boolean isOutOfBounds(int[] rows, int[] columns) { for (int i=0;i<rows.length;i++) { if ((rows[i] < 0)||(rowSize <= rows[i])) return true; } for (int i=0;i<columns.length;i++) { if ((columns[i] < 0)||(columnSize <= columns[i])) return true; } return false; } public final void setValues(Object[][] target, Object value, int[] rows, int[] columns) { for (int i=0;i<rows.length;i++) { int row = rows[i]; for (int j=0;j<columns.length;j++) { int column = columns[j]; target[row][column] = value; } } } }