/*******************************************************************************
* Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
******************************************************************************/
package com.opendoorlogistics.studio.tables.grid.adapter;
import java.awt.Color;
import java.util.concurrent.Callable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import com.opendoorlogistics.api.tables.ODLColumnType;
import com.opendoorlogistics.api.tables.ODLDatastore;
import com.opendoorlogistics.api.tables.ODLListener;
import com.opendoorlogistics.api.tables.ODLTable;
import com.opendoorlogistics.api.tables.ODLTableDefinition;
import com.opendoorlogistics.api.tables.ODLTableReadOnly;
import com.opendoorlogistics.api.tables.TableFlags;
import com.opendoorlogistics.core.tables.ColumnValueProcessor;
import com.opendoorlogistics.core.tables.utils.TableUtils;
import com.opendoorlogistics.core.utils.BiHashMap;
import com.opendoorlogistics.core.utils.strings.StandardisedStringSet;
import com.opendoorlogistics.studio.tables.grid.GridEditPermissions;
public final class SwingAdapter implements TableModel {
private ODLDatastore<? extends ODLTableReadOnly> ds;
private int tableId;
private boolean readOnly;
private final boolean enableListeners;
private final BiHashMap<TableModelListener, ODLListener> listeners = new BiHashMap<>();
private FilteredTableController filter;
private RowStyler rowStyler;
public SwingAdapter(ODLDatastore<? extends ODLTableReadOnly> ds, int tableId, boolean enableListeners, boolean readOnly, RowStyler rowStyler) {
this.ds = ds;
this.tableId = tableId;
this.enableListeners = enableListeners;
this.filter = new FilteredTableController(ds, tableId);
this.readOnly = readOnly;
this.rowStyler = rowStyler;
}
public void replaceData(ODLDatastore<? extends ODLTableReadOnly> ds, int tableId, boolean readOnly, RowStyler rowStyler) {
this.rowStyler = rowStyler;
if (enableListeners) {
throw new RuntimeException();
}
this.ds = ds;
this.tableId = tableId;
this.readOnly = readOnly;
// replace the filter object but take the old filter's state
this.filter = new FilteredTableController(ds, tableId, filter.getFilterState());
}
@Override
public int getRowCount() {
ODLTableReadOnly table = getTable();
return (table!=null?table.getRowCount():0)+ 1;
}
@Override
public int getColumnCount() {
ODLTableDefinition table = getTable();
return (table!=null?table.getColumnCount():0)+ 1;
}
// private int getSourceColumn(int index){
// return index;
// }
@Override
public String getColumnName(int columnIndex) {
if (columnIndex == 0) {
return "";
}
columnIndex--;
ODLTableDefinition table = getTable();
if(table!=null && columnIndex < table.getColumnCount()){
return table.getColumnName(columnIndex);
}
return "";
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return String.class;
}
columnIndex--;
ODLTableDefinition table = getTable();
ODLColumnType type = table!=null ? table.getColumnType(columnIndex):ODLColumnType.STRING;
if (type == ODLColumnType.COLOUR) {
return String.class;
}
if (type == ODLColumnType.TIME) {
return String.class;
}
return ColumnValueProcessor.getJavaClass(type);
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
ODLTableReadOnly table = getTable();
if(table==null){
return null;
}
if (rowIndex >= table.getRowCount()) {
return null;
}
if (columnIndex == 0) {
return Integer.toString(rowIndex + 1);
}
columnIndex--;
// check columns within range
if (columnIndex >= table.getColumnCount()) {
return null;
}
ODLColumnType ct = table.getColumnType(columnIndex);
if (ct == ODLColumnType.COLOUR || ct == ODLColumnType.TIME) {
return TableUtils.getValueAsString(table, rowIndex, columnIndex);
}
return table.getValueAt(rowIndex, columnIndex);
}
@Override
public void addTableModelListener(TableModelListener l) {
if (enableListeners) {
Listener listener = new Listener();
listeners.put(l, listener);
ds.addListener(listener, tableId);
}
}
@Override
public void removeTableModelListener(TableModelListener l) {
if (enableListeners) {
ODLListener listener = listeners.getB(l);
listeners.removeUsingA(l);
ds.removeListener(listener);
}
}
public ODLTableReadOnly getTable() {
return filter.getTable();
}
public void dispose() {
}
private class Listener implements ODLListener {
@Override
public void tableChanged(int tableId, int firstRow, int lastRow) {
// update the filter first of all
if (filter != null) {
filter.update();
}
// create the event with all rows changed
final TableModelEvent tme = new TableModelEvent(SwingAdapter.this, -1, Integer.MAX_VALUE, TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE);
// if(lastRow == Integer.MAX_VALUE){
// tme = new TableModelEvent(SwingAdapterReadOnly.this, -1, Integer.MAX_VALUE, TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE);
//
// }else{
// tme = new TableModelEvent(SwingAdapterReadOnly.this, firstRow, lastRow);
// }
// fire the listener
final TableModelListener tml = listeners.getA(this);
if (SwingUtilities.isEventDispatchThread()) {
tml.tableChanged(tme);
} else {
try {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
tml.tableChanged(tme);
}
});
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
@Override
public void datastoreStructureChanged() {
// TODO Auto-generated method stub
}
@Override
public ODLListenerType getType() {
return ODLListenerType.TABLE_CHANGED;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (readOnly) {
return false;
}
if (columnIndex == 0) {
return false;
}
int tableCol = columnIndex;
tableCol--;
ODLTableReadOnly table = getTable();
if(table==null){
return false;
}
if (table == null || table.getColumnType(tableCol) == ODLColumnType.IMAGE) {
return false;
}
// check for whole column being read-only
if ((table.getColumnFlags(tableCol) & TableFlags.FLAG_IS_READ_ONLY) != 0) {
return false;
}
// or whole row being read-only as its linked data
long rowId = table.getRowId(rowIndex);
long rowFlags = table.getRowFlags(rowId);
if((rowFlags & TableFlags.FLAG_LINKED_EXCEL_READ_ONLY_DATA) == TableFlags.FLAG_LINKED_EXCEL_READ_ONLY_DATA){
return false;
}
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (readOnly) {
return;
}
ODLTable table = (ODLTable) getTable();
if(table==null){
return;
}
columnIndex--;
if (columnIndex < 0) {
return;
}
// check columns within range
if (columnIndex >= table.getColumnCount()) {
return;
}
int finalCol = columnIndex;
TableUtils.runTransaction(ds, new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
// grow if its not an empty or null string
if (aValue != null && aValue.toString().length() > 0) {
while (rowIndex >= table.getRowCount()) {
table.createEmptyRow(-1);
}
}
if (rowIndex < table.getRowCount()) {
table.setValueAt(aValue, rowIndex, finalCol);
}
return true;
}
});
}
public void setColumnFilter(String column, String value) {
filter.setColumnFilter(column, value);
}
public String getColumnFilter(String column) {
return filter.getFilterState().getColumnFilter(column);
}
public String getTableName(){
return getTable()!=null?getTable().getName() : "";
}
public StandardisedStringSet getUniqueUnfilteredColumnValues(int col){
// get the unfiltered table
StandardisedStringSet ret = new StandardisedStringSet(true);
ODLTableReadOnly unfiltered = ds.getTableByImmutableId(tableId);
if(col>0 && unfiltered!=null){
col--;
int n = unfiltered.getRowCount();
for(int i =0 ; i<n;i++){
String s = TableUtils.getValueAsString(unfiltered, i, col);
if(s==null){
s="";
}
ret.add(s);
}
}
return ret;
}
public int getTableId(){
return tableId;
}
public GridEditPermissions getPermissions(){
ODLTableDefinition table = getTable();
if(table==null){
return new GridEditPermissions();
}
GridEditPermissions ret = GridEditPermissions.create(table, filter.isFiltered()==false);
return ret;
}
public Color getRowColour(int row){
if(rowStyler!=null){
ODLTableReadOnly table = getTable();
if(table!=null){
long id = table.getRowId(row);
if(id!=-1){
return rowStyler.getRowFontColour(id);
}
}
}
return null;
}
}