/** * */ package org.korsakow.ide.ui.components.code; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; import org.korsakow.ide.code.k5.K5Code; public class CodeTableModel extends AbstractTableModel { public static final int EVENT_SORT = 100; public static final int TIME_COLUMN = 0; public static final int CODE_COLUMN = 1; public static final int MAXLINKS_COLUMN = 2; private final Hashtable<Integer, String> identifiers = new Hashtable<Integer, String>(); List<CodeRow> rows = new ArrayList<CodeRow>(); public CodeTableModel() { addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { if (e.getColumn() == TIME_COLUMN) sort(); } }); rows.add(new CodeRow(null, new K5Code(""), null)); } private boolean isLastRowEmpty() { return getRowCount()!=0 && getTimeAt(getRowCount()-1)==null && getCodeAt(getRowCount()-1).getRawCode().trim().length()==0; } public void clear() { List<CodeRow> oldRows = rows; rows = new ArrayList<CodeRow>(); fireTableRowsDeleted(0, oldRows.size()); } public int addRow(Long time, K5Code code) { int index = addRowInternal(time, code); fireTableRowsInserted(index, index); return index; } /** * does not notify */ private int addRowInternal(Long time, K5Code code) { int index = isLastRowEmpty()?getRowCount()-1:getRowCount(); CodeRow row = new CodeRow(time, code, null); rows.add(index, row); return rows.indexOf(row); } public void removeRows(List<Integer> toRemove) { toRemove = new ArrayList<Integer>(toRemove); Collections.sort(toRemove); // reverse iterate so that the input indices don't change with each removal for (int i = toRemove.size() - 1; i >= 0; --i) { int row = toRemove.get(i); rows.remove(row); fireTableRowsDeleted(row, row); } } public void removeRow(int row) { rows.remove(row); fireTableRowsDeleted(row, row); } /** * Made public for Unit tests. */ public CodeRow getRow(int row) { return rows.get(row); } public int indexOfRow(CodeRow row) { return rows.indexOf(row); } public int getEmptyRow() { for (CodeRow row : rows) if (row.getCode().getRawCode().isEmpty()) return rows.indexOf(row); // should not reach here... return -1; } public int getColumnCount() { return identifiers.size(); } public int getRowCount() { return rows.size(); } public Object getValueAt(int rowIndex, int columnIndex) { return getRow(rowIndex).getValueAt(columnIndex); } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { getRow(rowIndex).setValueAt(columnIndex, aValue); fireTableCellUpdated(rowIndex, columnIndex); } public Long getTimeAt(int rowIndex) { return getRow(rowIndex).getTime(); } public void setTimeAt(Long time, int rowIndex) { setValueAt(time, rowIndex, TIME_COLUMN); } public void setCodeAt(K5Code code, int rowIndex) { setValueAt(code, rowIndex, CODE_COLUMN); } public void setMaxLinks(Long maxlinks, int rowIndex) { setValueAt(maxlinks, rowIndex, MAXLINKS_COLUMN); } public K5Code getCodeAt(int rowIndex) { return getRow(rowIndex).getCode(); } public Long getMaxLinksAt(int rowIndex) { return getRow(rowIndex).getMaxLinks(); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } public void setColumnName(int column, String identifier) { identifiers.put(column, identifier); } @Override public String getColumnName(int column) { return identifiers.get(column); } @SuppressWarnings("unchecked") public void sort() { List<CodeRow> previousOrdering = new ArrayList<CodeRow>(rows); Collections.sort(rows); fireTableSorted(new TableModelSortEvent(this, previousOrdering)); } public void fireTableSorted(TableModelSortEvent e) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i+1] instanceof CodeTableModelListener) { ((CodeTableModelListener)listeners[i+1]).tableSorted(e); } } } }