package simplesheet.model.defaults;
import simplesheet.model.selection.CellPosition;
import simplesheet.model.SheetModelListener;
import simplesheet.model.cell.TableCell;
import simplesheet.model.column.Column;
import simplesheet.model.row.Row;
import simplesheet.model.SheetModel;
import java.awt.Dimension;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author axe
*/
public class SheetModelDefault implements SheetModel {
private static final EmptyCell EMPTY_CELL = new EmptyCell();
private static final int ROW = 0;
private static final int COL = 1;
private List<SheetModelListener> listeners = new LinkedList<SheetModelListener>();
//[rows][cols]
private TableCell cells[][];
private int span[][][];
private Column cols[];
private Row rows[];
public SheetModelDefault(int rows, int cols) {
cells = new TableCell[rows][cols];
span = new int[rows][cols][2];
this.cols = new Column[cols];
for(int i=0; i<cols; i++) {
this.cols[i] = new Column(i);
}
this.rows = new Row[rows];
for(int i=0; i<rows; i++) {
this.rows[i] = new Row(i);
}
}
@Override
public TableCell getValueAt(CellPosition pos) {
CellPosition point = getOrigin(pos);
TableCell cell = cells[point.row][point.col];
if(cell == null) {
return EMPTY_CELL;
}
return cell;
}
@Override
public int getRowCount() {
return rows.length;
}
@Override
public int getColumnCount() {
return cols.length;
}
public void initCell(CellPosition pos, TableCell cell) {
CellPosition point = getOrigin(pos);
cells[point.row][point.col] = cell;
fireSheetCellUpdated(point);
}
/**
*
* @param col
* @param row
* @param width
* @param height
* @return
*/
public boolean combine(CellPosition pos, int height, int width) {
CellPosition origin = getOrigin(pos);
if (origin == null
|| origin.col + width > getColumnCount()
|| origin.row + height > getRowCount()
|| width == 0
|| height == 0
|| (width == 1 && height == 1)) {
assert false : "index of bounds";
return false;
}
//check for already combined
for (int iCol = origin.col; iCol < origin.col+width; iCol++) {
for (int iRow = origin.row; iRow < origin.row + height; iRow++) {
if ((span[iRow][iCol][COL] != 0) || (span[iRow][iCol][ROW] != 0)) {
assert false :"already combined";
return false;
}
}
}
//combine
int dx = 0;
for (int iCol = origin.col; iCol < origin.col+width; iCol++,dx--) {
int dy = 0;
for (int iRow = origin.row; iRow < origin.row + height; iRow++,dy--) {
span[iRow][iCol][COL] = dx;
span[iRow][iCol][ROW] = dy;
}
}
span[origin.row][origin.col][COL] = width;
span[origin.row][origin.col][ROW] = height;
fireSheetDataChanged();
return true;
}
/**
*
* @param col
* @param row
*/
public boolean split(CellPosition pos) {
CellPosition origin = getOrigin(pos);
if (origin == null) {
assert false : "index of bounds";
return false;
}
Dimension size = getSize(origin);
for (int iCol = origin.col; iCol < origin.col+size.width; iCol++) {
for (int iRow = origin.row; iRow < origin.row + size.height; iRow++) {
span[iRow][iCol][COL] = span[iRow][iCol][ROW] = 0;
}
}
return true;
}
@Override
public CellPosition getOrigin(CellPosition pos) {
if (pos.row<0 || pos.row >= getRowCount()
|| pos.col < 0 || pos.col >= getColumnCount()) {
return null;
}
int r = pos.row;
int c = pos.col;
if(span[pos.row][pos.col][ROW] < 0 || span[pos.row][pos.col][COL] < 0) {
c += span[pos.row][pos.col][COL];
r += span[pos.row][pos.col][ROW];
}
return new CellPosition(r, c);
}
@Override
public Dimension getSize(CellPosition pos) {
if(span[pos.row][pos.col][ROW] == 0 && span[pos.row][pos.col][COL] == 0) {
return new Dimension(1, 1);
}
int r = pos.row;
int c = pos.col;
if((span[pos.row][pos.col][ROW] < 0
|| span[pos.row][pos.col][COL] < 0)) {
c += span[pos.row][pos.col][COL];
r += span[pos.row][pos.col][ROW];
}
return new Dimension(span[r][c][COL], span[r][c][ROW]);
}
@Override
public void addSheetModelListener(SheetModelListener l) {
listeners.add(l);
}
@Override
public void removeSheetModelListener(SheetModelListener l) {
listeners.remove(l);
}
public void fireSheetCellUpdated(CellPosition pos) {
for(SheetModelListener l: listeners) {
l.cellUpdated(pos);
}
}
public void fireSheetDataChanged() {
for(SheetModelListener l: listeners) {
l.dataChanged();
}
}
@Override
public Column getColumn(int col) {
return cols[col];
}
@Override
public Row getRow(int row) {
return rows[row];
}
}