Skip to content

Commit

Permalink
Issue mabe02#216: New fix for this issue; use listeners instead
Browse files Browse the repository at this point in the history
  • Loading branch information
mabe02 committed Mar 13, 2016
1 parent d5d1cc6 commit 65a4231
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 3 deletions.
33 changes: 33 additions & 0 deletions src/main/java/com/googlecode/lanterna/gui2/table/Table.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.googlecode.lanterna.gui2.*;
import com.googlecode.lanterna.input.KeyStroke;

import java.util.List;

/**
* The table class is an interactable component that displays a grid of cells containing data along with a header of
* labels. It supports scrolling when the number of rows and/or columns gets too large to fit and also supports
Expand All @@ -13,6 +15,7 @@
*/
public class Table<V> extends AbstractInteractableComponent<Table<V>> {
private TableModel<V> tableModel;
private TableModel.Listener<V> tableModelListener; // Used to invalidate the table whenever the model changes
private TableHeaderRenderer<V> tableHeaderRenderer;
private TableCellRenderer<V> tableCellRenderer;
private Runnable selectAction;
Expand Down Expand Up @@ -45,6 +48,34 @@ public Table(String... columnLabels) {
this.selectedRow = 0;
this.selectedColumn = -1;
this.escapeByArrowKey = true;

this.tableModelListener = new TableModel.Listener<V>() {
@Override
public void onRowAdded(TableModel<V> model, int index) {
invalidate();
}

@Override
public void onRowRemoved(TableModel<V> model, int index, List<V> oldRow) {
invalidate();
}

@Override
public void onColumnAdded(TableModel<V> model, int index) {
invalidate();
}

@Override
public void onColumnRemoved(TableModel<V> model, int index, String oldHeader, List<V> oldColumn) {
invalidate();
}

@Override
public void onCellChanged(TableModel<V> model, int row, int column, V oldValue, V newValue) {
invalidate();
}
};
this.tableModel.addListener(tableModelListener);
}

/**
Expand All @@ -64,7 +95,9 @@ public synchronized Table<V> setTableModel(TableModel<V> tableModel) {
if(tableModel == null) {
throw new IllegalArgumentException("Cannot assign a null TableModel");
}
this.tableModel.removeListener(tableModelListener);
this.tableModel = tableModel;
this.tableModel.addListener(tableModelListener);
invalidate();
return this;
}
Expand Down
92 changes: 89 additions & 3 deletions src/main/java/com/googlecode/lanterna/gui2/table/TableModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,56 @@
* @author Martin
*/
public class TableModel<V> {

/**
* 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
* @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
* @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
* @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
* @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
* @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
Expand All @@ -19,6 +67,7 @@ public class TableModel<V> {
public TableModel(String... columnLabels) {
this.columns = new ArrayList<String>(Arrays.asList(columnLabels));
this.rows = new ArrayList<List<V>>();
this.listeners = new ArrayList<Listener<V>>();
}

/**
Expand Down Expand Up @@ -96,6 +145,9 @@ public synchronized TableModel<V> addRow(Collection<V> values) {
public synchronized TableModel<V> insertRow(int index, Collection<V> values) {
ArrayList<V> list = new ArrayList<V>(values);
rows.add(index, list);
for(Listener listener: listeners) {
listener.onRowAdded(this, index);
}
return this;
}

Expand All @@ -105,7 +157,10 @@ public synchronized TableModel<V> insertRow(int index, Collection<V> values) {
* @return Itself
*/
public synchronized TableModel<V> removeRow(int index) {
rows.remove(index);
List<V> removedRow = rows.remove(index);
for(Listener listener: listeners) {
listener.onRowRemoved(this, index, removedRow);
}
return this;
}

Expand Down Expand Up @@ -167,6 +222,10 @@ public synchronized TableModel<V> insertColumn(int index, String label, V[] newC
row.add(index, null);
}
}

for(Listener listener: listeners) {
listener.onColumnAdded(this, index);
}
return this;
}

Expand All @@ -176,9 +235,13 @@ public synchronized TableModel<V> insertColumn(int index, String label, V[] newC
* @return Itself
*/
public synchronized TableModel<V> removeColumn(int index) {
columns.remove(index);
String removedColumnHeader = columns.remove(index);
List<V> removedColumn = new ArrayList<V>();
for(List<V> row : rows) {
row.remove(index);
removedColumn.add(row.remove(index));
}
for(Listener listener: listeners) {
listener.onColumnRemoved(this, index, removedColumnHeader, removedColumn);
}
return this;
}
Expand Down Expand Up @@ -223,6 +286,29 @@ public synchronized TableModel<V> setCell(int columnIndex, int rowIndex, V value
return this;
}
row.set(columnIndex, value);
for(Listener 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
* @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
* @param listener {@link Listener} to deregister from this model
* @return Itself
*/
public TableModel<V> removeListener(Listener<V> listener) {
listeners.remove(listener);
return this;
}
}
5 changes: 5 additions & 0 deletions src/test/java/com/googlecode/lanterna/issue/Issue216.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.gui2.*;
import com.googlecode.lanterna.gui2.Button;
import com.googlecode.lanterna.gui2.GridLayout;
import com.googlecode.lanterna.gui2.Label;
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.table.Table;
import com.googlecode.lanterna.gui2.table.TableModel;
import com.googlecode.lanterna.screen.Screen;
import com.googlecode.lanterna.screen.TerminalScreen;
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
import com.googlecode.lanterna.terminal.Terminal;

import java.awt.*;
import java.io.IOException;

/**
Expand Down

0 comments on commit 65a4231

Please sign in to comment.