package org.geogebra.web.html5.util; import java.util.ArrayList; import org.geogebra.common.gui.view.spreadsheet.MyTable; import org.geogebra.common.main.SpreadsheetTableModel; import org.geogebra.common.util.debug.Log; import org.geogebra.web.html5.main.AppW; /** * Web implementation of the table model * */ public class SpreadsheetTableModelW extends SpreadsheetTableModel { /** * Listens to changes in table size and values */ public interface ChangeListener { /** * Fired when a row/column is added/removed */ public void dimensionChange(); /** * Fired when a value is changed */ public void valueChange(); } private MyTable table; private ChangeListener listener = null; // try with one-dimension ArrayList to represent two dimensions private ArrayList<Object> defaultTableModel; // it is easier to store the rowNum and colNum than computing them private int rowNum = 0; private int colNum = 0; /** * Constructor * * @param app * application * @param rows * number of rows * @param columns * number of columns */ public SpreadsheetTableModelW(AppW app, int rows, int columns) { super(app); rowNum = rows; colNum = columns; defaultTableModel = new ArrayList<Object>(rows * columns); for (int i = 0; i < rows * columns; i++) { defaultTableModel.add(null); } attachView(); isIniting = false; } /** * Gets the JTable table model. * * @return instance of Swing DefaultTableModel class */ public ArrayList<Object> getDefaultTableModel() { return defaultTableModel; } /** * Estabilishes connection to the table and synces all values from model to * table * * @param newTable * table implementation */ public void attachMyTable(MyTable newTable) { this.table = newTable; Object value; if (newTable != null) { for (int i = 0; i < rowNum; i++) { for (int j = 0; j < colNum; j++) { if ((value = getValueAt(i, j)) != null) { newTable.updateTableCellValue(value, i, j); } } } } } @Override public int getRowCount() { return rowNum; } @Override public int getColumnCount() { return colNum; } @Override public void setRowCount(int rowCount) { if (rowNum == rowCount) { return; } else if (rowNum > rowCount) { for (int i = rowNum * colNum - 1; i >= rowCount * colNum; i--) { defaultTableModel.remove(i); } } else { defaultTableModel.ensureCapacity(rowCount * colNum); for (int i = rowNum * colNum; i < rowCount * colNum; i++) { defaultTableModel.add(null); } } rowNum = rowCount; if (listener != null) { listener.dimensionChange(); } } @Override public void setColumnCount(int columnCount) { if (colNum == columnCount) { return; } else if (colNum > columnCount) { for (int i = rowNum - 1; i >= 0; i--) { for (int j = colNum - 1; j >= columnCount; j--) { defaultTableModel.remove(i * colNum + j); } } } else { defaultTableModel.ensureCapacity(rowNum * columnCount); for (int i = rowNum - 1; i >= 0; i--) { for (int j = colNum; j < columnCount; j++) { if (i * colNum + j >= defaultTableModel.size()) { defaultTableModel.add(null); } else { defaultTableModel.add(i * colNum + j, null); } } } } colNum = columnCount; if (listener != null) { listener.dimensionChange(); } } @Override public Object getValueAt(int row, int column) { return defaultTableModel.get(row * colNum + column); } @Override public void setValueAt(Object value, int row, int column) { // Log.debug(row + "," + column); // update column count if needed if (column >= getColumnCount()) { setColumnCount(column + 1); if (listener != null) { listener.dimensionChange(); } } if (row >= getRowCount()) { setRowCount(row + 1); if (listener != null) { listener.dimensionChange(); } } if ((value != null || defaultTableModel.get(row * colNum + column) != null)) { defaultTableModel.set(row * colNum + column, value); if (table != null) { table.updateTableCellValue(value, row, column); // do this after updateTableCellValue, as it does no harm // and the valueChange might need the table cell value! if (listener != null) { listener.valueChange(); } } } } @Override public boolean hasFocus() { Log.debug("unimplemented"); return false; } @Override public boolean isShowing() { return false; } /** * @param cl * change listener */ public void setChangeListener(ChangeListener cl) { listener = cl; } @Override public boolean suggestRepaint() { // repaint not needed return false; } }