/*
* This file is part of lanterna (http://code.google.com/p/lanterna/).
*
* lanterna is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2010-2020 Martin Berglund
*/
package com.googlecode.lanterna.gui2.table;
import java.util.*;
A TableModel
contains the data model behind a table, here is where all the action cell values and header labels are stored. Author: Martin
/**
* 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<V> {
Listener interface for the TableModel
class which can be attached to a TableModel
to be notified of changes to the table model. Type parameters: - <V> – Value type stored in the table
/**
* Listener interface for the {@link TableModel} class which can be attached to a {@link TableModel} to be notified
* of changes to the table model.
* @param <V> Value type stored in the table
*/
public interface Listener<V> {
Called when a new row has been added to the model
Params: - model – Model the row was added to
- index – Index of the new row
/**
* Called when a new row has been added to the model
* @param model Model the row was added to
* @param index Index of the new row
*/
void onRowAdded(TableModel<V> model, int index);
Called when a row has been removed from the model
Params: - model – Model the row was removed from
- index – Index of the removed row
- oldRow – Content of the row that was removed
/**
* Called when a row has been removed from the model
* @param model Model the row was removed from
* @param index Index of the removed row
* @param oldRow Content of the row that was removed
*/
void onRowRemoved(TableModel<V> model, int index, List<V> oldRow);
Called when a new column has been added to the model
Params: - model – Model the column was added to
- index – Index of the new column
/**
* Called when a new column has been added to the model
* @param model Model the column was added to
* @param index Index of the new column
*/
void onColumnAdded(TableModel<V> model, int index);
Called when a column has been removed from the model
Params: - model – Model the column was removed from
- index – Index of the removed column
- oldHeader – Header the removed column had
- oldColumn – Values in the removed column
/**
* Called when a column has been removed from the model
* @param model Model the column was removed from
* @param index Index of the removed column
* @param oldHeader Header the removed column had
* @param oldColumn Values in the removed column
*/
void onColumnRemoved(TableModel<V> model, int index, String oldHeader, List<V> oldColumn);
Called when an existing cell had its content updated
Params: - model – Model that was modified
- row – Row index of the modified cell
- column – Column index of the modified cell
- oldValue – Previous value of the cell
- newValue – New value of the cell
/**
* Called when an existing cell had its content updated
* @param model Model that was modified
* @param row Row index of the modified cell
* @param column Column index of the modified cell
* @param oldValue Previous value of the cell
* @param newValue New value of the cell
*/
void onCellChanged(TableModel<V> model, int row, int column, V oldValue, V newValue);
}
private final List<String> columns;
private final List<List<V>> rows;
private final List<Listener<V>> listeners;
Default constructor, creates a new model with same number of columns as labels supplied
Params: - columnLabels – Labels for the column headers
/**
* 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<String>(Arrays.asList(columnLabels));
this.rows = new ArrayList<List<V>>();
this.listeners = new ArrayList<Listener<V>>();
}
Returns the number of columns in the model
Returns: Number of columns in the model
/**
* 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
Returns: Number of rows in the model
/**
* 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
Returns: All rows in the model as a list of lists containing the data as elements
/**
* 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<List<V>> getRows() {
List<List<V>> copy = new ArrayList<List<V>>();
for(List<V> row: rows) {
copy.add(new ArrayList<V>(row));
}
return copy;
}
Returns all column header label as a list of strings
Returns: All column header label as a list of strings
/**
* Returns all column header label as a list of strings
* @return All column header label as a list of strings
*/
public synchronized List<String> getColumnLabels() {
return new ArrayList<String>(columns);
}
Returns a row from the table as a list of the cell data
Params: - index – Index of the row to return
Returns: Row from the table as a list of the cell data
/**
* 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<V> getRow(int index) {
return new ArrayList<V>(rows.get(index));
}
Adds a new row to the table model at the end
Params: - values – Data to associate with the new row, mapped column by column in order
Returns: Itself
/**
* 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<V> addRow(V... values) {
addRow(Arrays.asList(values));
return this;
}
Adds a new row to the table model at the end
Params: - values – Data to associate with the new row, mapped column by column in order
Returns: Itself
/**
* 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<V> addRow(Collection<V> values) {
insertRow(getRowCount(), values);
return this;
}
Inserts a new row to the table model at a particular index
Params: - index – Index the new row should have, 0 means the first row and row count will append the row at the
end
- values – Data to associate with the new row, mapped column by column in order
Returns: Itself
/**
* 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 <i>row count</i> 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<V> insertRow(int index, Collection<V> values) {
ArrayList<V> list = new ArrayList<V>(values);
rows.add(index, list);
for(Listener<V> listener: listeners) {
listener.onRowAdded(this, index);
}
return this;
}
Removes a row at a particular index from the table model
Params: - index – Index of the row to remove
Returns: Itself
/**
* Removes a row at a particular index from the table model
* @param index Index of the row to remove
* @return Itself
*/
public synchronized TableModel<V> removeRow(int index) {
List<V> removedRow = rows.remove(index);
for(Listener<V> listener: listeners) {
listener.onRowRemoved(this, index, removedRow);
}
return this;
}
Removes all rows from the table, this will trigger listeners for each row
Returns: Itself
/**
* Removes all rows from the table, this will trigger listeners for each row
* @return Itself
*/
public synchronized TableModel<V> clear() {
while (rows.size() > 0) {
removeRow(0);
}
return this;
}
Returns the label of a column header
Params: - index – Index of the column to retrieve the header label for
Returns: Label of the column selected
/**
* 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
Params: - index – Index of the column to update the header label for
- newLabel – New label to assign to the column header
Returns: Itself
/**
* 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<V> 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 newColumnValues
. Params: - label – Label for the header of the new column
- 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...
Returns: Itself
/**
* 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<V> 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 newColumnValues
. Params: - index – Index for the new column
- label – Label for the header of the new column
- 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...
Returns: Itself
/**
* 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<V> insertColumn(int index, String label, V[] newColumnValues) {
columns.add(index, label);
for(int i = 0; i < rows.size(); i++) {
List<V> 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);
}
}
for(Listener<V> listener: listeners) {
listener.onColumnAdded(this, index);
}
return this;
}
Removes a column from the table model
Params: - index – Index of the column to remove
Returns: Itself
/**
* Removes a column from the table model
* @param index Index of the column to remove
* @return Itself
*/
public synchronized TableModel<V> removeColumn(int index) {
String removedColumnHeader = columns.remove(index);
List<V> removedColumn = new ArrayList<V>();
for(List<V> row : rows) {
removedColumn.add(row.remove(index));
}
for(Listener<V> listener: listeners) {
listener.onColumnRemoved(this, index, removedColumnHeader, removedColumn);
}
return this;
}
Returns the cell value stored at a specific column/row coordinate.
Params: - columnIndex – Column index of the cell
- rowIndex – Row index of the cell
Returns: The data value stored in this cell
/**
* 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.
Params: - columnIndex – Column index of the cell
- rowIndex – Row index of the cell
- value – New value to assign to the cell
Returns: Itself
/**
* 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<V> setCell(int columnIndex, int rowIndex, V value) {
getCell(columnIndex, rowIndex);
List<V> 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);
for(Listener<V> listener: listeners) {
listener.onCellChanged(this, rowIndex, columnIndex, existingValue, value);
}
return this;
}
Adds a listener to this table model that will be notified whenever the model changes
Params: - listener –
Listener
to register with this model
Returns: Itself
/**
* Adds a listener to this table model that will be notified whenever the model changes
* @param listener {@link Listener} to register with this model
* @return Itself
*/
public TableModel<V> addListener(Listener<V> listener) {
listeners.add(listener);
return this;
}
Removes a listener from this model so that it will no longer receive any notifications when the model changes
Params: - listener –
Listener
to deregister from this model
Returns: Itself
/**
* Removes a listener from this model so that it will no longer receive any notifications when the model changes
* @param listener {@link Listener} to deregister from this model
* @return Itself
*/
public TableModel<V> removeListener(Listener<V> listener) {
listeners.remove(listener);
return this;
}
}