package com.googlecode.lanterna.gui2.table; import java.util.*; /** * A {@code TableModel} contains the data model behind a table, here is where all the action cell values and header * labels are stored. * * @author Martin */ public class TableModel { private final List columns; private final List> rows; /** * Default constructor, creates a new model with same number of columns as labels supplied * @param columnLabels Labels for the column headers */ public TableModel(String... columnLabels) { this.columns = new ArrayList(Arrays.asList(columnLabels)); this.rows = new ArrayList>(); } /** * Returns the number of columns in the model * @return Number of columns in the model */ public synchronized int getColumnCount() { return columns.size(); } /** * Returns number of rows in the model * @return Number of rows in the model */ public synchronized int getRowCount() { return rows.size(); } /** * Returns all rows in the model as a list of lists containing the data as elements * @return All rows in the model as a list of lists containing the data as elements */ public synchronized List> getRows() { List> copy = new ArrayList>(); for(List row: rows) { copy.add(new ArrayList(row)); } return copy; } /** * Returns all column header label as a list of strings * @return All column header label as a list of strings */ public synchronized List getColumnLabels() { return new ArrayList(columns); } /** * Returns a row from the table as a list of the cell data * @param index Index of the row to return * @return Row from the table as a list of the cell data */ public synchronized List getRow(int index) { return new ArrayList(rows.get(index)); } /** * Adds a new row to the table model at the end * @param values Data to associate with the new row, mapped column by column in order * @return Itself */ public synchronized TableModel addRow(V... values) { addRow(Arrays.asList(values)); return this; } /** * Adds a new row to the table model at the end * @param values Data to associate with the new row, mapped column by column in order * @return Itself */ public synchronized TableModel addRow(Collection values) { insertRow(getRowCount(), values); return this; } /** * Inserts a new row to the table model at a particular index * @param index Index the new row should have, 0 means the first row and row count will append the row at the * end * @param values Data to associate with the new row, mapped column by column in order * @return Itself */ public synchronized TableModel insertRow(int index, Collection values) { ArrayList list = new ArrayList(values); rows.add(index, list); return this; } /** * Removes a row at a particular index from the table model * @param index Index of the row to remove * @return Itself */ public synchronized TableModel removeRow(int index) { rows.remove(index); return this; } /** * Returns the label of a column header * @param index Index of the column to retrieve the header label for * @return Label of the column selected */ public synchronized String getColumnLabel(int index) { return columns.get(index); } /** * Updates the label of a column header * @param index Index of the column to update the header label for * @param newLabel New label to assign to the column header * @return Itself */ public synchronized TableModel setColumnLabel(int index, String newLabel) { columns.set(index, newLabel); return this; } /** * Adds a new column into the table model as the last column. You can optionally supply values for the existing rows * through the {@code newColumnValues}. * @param label Label for the header of the new column * @param newColumnValues Optional values to assign to the existing rows, where the first element in the array will * be the value of the first row and so on... * @return Itself */ public synchronized TableModel addColumn(String label, V[] newColumnValues) { return insertColumn(getColumnCount(), label, newColumnValues); } /** * Adds a new column into the table model at a specified index. You can optionally supply values for the existing * rows through the {@code newColumnValues}. * @param index Index for the new column * @param label Label for the header of the new column * @param newColumnValues Optional values to assign to the existing rows, where the first element in the array will * be the value of the first row and so on... * @return Itself */ public synchronized TableModel insertColumn(int index, String label, V[] newColumnValues) { columns.add(index, label); for(int i = 0; i < rows.size(); i++) { List row = rows.get(i); //Pad row with null if necessary for(int j = row.size(); j < index; j++) { row.add(null); } if(newColumnValues != null && i < newColumnValues.length && newColumnValues[i] != null) { row.add(index, newColumnValues[i]); } else { row.add(index, null); } } return this; } /** * Removes a column from the table model * @param index Index of the column to remove * @return Itself */ public synchronized TableModel removeColumn(int index) { columns.remove(index); for(List row : rows) { row.remove(index); } return this; } /** * Returns the cell value stored at a specific column/row coordinate. * @param columnIndex Column index of the cell * @param rowIndex Row index of the cell * @return The data value stored in this cell */ public synchronized V getCell(int columnIndex, int rowIndex) { if(rowIndex < 0 || columnIndex < 0) { throw new IndexOutOfBoundsException("Invalid row or column index: " + rowIndex + " " + columnIndex); } else if (rowIndex >= getRowCount()) { throw new IndexOutOfBoundsException("TableModel has " + getRowCount() + " rows, invalid access at rowIndex " + rowIndex); } if(columnIndex >= getColumnCount()) { throw new IndexOutOfBoundsException("TableModel has " + columnIndex + " columns, invalid access at columnIndex " + columnIndex); } return rows.get(rowIndex).get(columnIndex); } /** * Updates the call value stored at a specific column/row coordinate. * @param columnIndex Column index of the cell * @param rowIndex Row index of the cell * @param value New value to assign to the cell * @return Itself */ public synchronized TableModel setCell(int columnIndex, int rowIndex, V value) { getCell(columnIndex, rowIndex); List row = rows.get(rowIndex); //Pad row with null if necessary for(int j = row.size(); j < columnIndex; j++) { row.add(null); } V existingValue = row.get(columnIndex); if(existingValue == value) { return this; } row.set(columnIndex, value); return this; } }