/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.client.forms.components.model.grid.models;
import com.eas.client.forms.components.model.grid.columns.ModelColumn;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.runtime.JSType;
/**
* Table model, getting and setting data to an arbitrary rowset. Gets data from
* an arbitrary rowset or from a script.
*
* @author mg
*/
public class ArrayTableModel extends ArrayModel implements TableModel {
protected Set<TableModelListener> listeners = new HashSet<>();
protected Map<Object, Integer> locator = new HashMap();
/**
* Constructor, accepting a elements rowset.
*
* @param aColumns
* @param aData
* @param aOnRender
*/
public ArrayTableModel(TableColumnModel aColumns, JSObject aData, JSObject aOnRender) {
super(aColumns, aData, aOnRender);
}
@Override
public int getRowCount() {
int rowCount = data != null ? JSType.toInteger(data.getMember("length")) : 0;
return rowCount > 0 && rowCount != Integer.MAX_VALUE ? rowCount : 0;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex >= 0 && columnIndex < columns.getColumnCount()) {
Object oElement = data.getSlot(rowIndex);
if (oElement instanceof JSObject) {
return getValue((JSObject) oElement, columnIndex);
} else {
return null;
}
} else {
return null;
}
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex >= 0 && columnIndex < columns.getColumnCount()) {
Object oElement = data.getSlot(rowIndex);
if (oElement instanceof JSObject) {
Object oldValue = getValue((JSObject) oElement, columnIndex);
if (!Objects.equals(oldValue, aValue)) {
setValue((JSObject) oElement, columnIndex, aValue);
}
}
}
}
private void postEvent(TableModelEvent e) {
locator = null;
listeners.stream().forEach((l) -> {
l.tableChanged(e);
});
}
@Override
public void addTableModelListener(TableModelListener l) {
listeners.add(l);
}
@Override
public void removeTableModelListener(TableModelListener l) {
listeners.remove(l);
}
public void fireElementDeleted(int aRowIndex) {
TableModelEvent e = new TableModelEvent(this, aRowIndex, aRowIndex, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE);
postEvent(e);
}
public void fireElementInserted(int aRowIndex) {
TableModelEvent e = new TableModelEvent(this, aRowIndex, aRowIndex, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
postEvent(e);
}
/**
* Fires an event, that tells all listeners that elements structure has been
* changed.
*/
@Override
public void fireElementsChanged() {
TableModelEvent e = new TableModelEvent(this, TableModelEvent.HEADER_ROW);
postEvent(e);
}
/**
* Fires an event, that tells all listeners that data in all elements have
* been changed, but elements structure havn't been changed.
*/
@Override
public void fireElementsDataChanged() {
TableModelEvent e = new TableModelEvent(this, 0, getRowCount() - 1, TableModelEvent.ALL_COLUMNS);
postEvent(e);
}
public void fireElementsFieldChanged(String aElementsField) {
for (int i = 0; i < columns.getColumnCount(); i++) {
ModelColumn col = (ModelColumn) columns.getColumn(i);
if (col.getField() == null ? aElementsField == null : col.getField().equals(aElementsField)) {
int modelColumnIndex = col.getModelIndex();
if (modelColumnIndex != -1) {
TableModelEvent e = new TableModelEvent(this, 0, getRowCount() - 1, modelColumnIndex);
postEvent(e);
}
}
}
}
/**
* Fires an event, occuring when data or rowset structure of column's rowset
* is changed. It takes place when column's rowset and elements rowset are
* not same.
*
* @param aColumn ModelColumn instance, the change is related to.
* @see ModelColumn
*/
@Override
public void fireColumnFieldChanged(ModelColumn aColumn) {
int colIndex = aColumn.getModelIndex();
if (colIndex != -1) {
TableModelEvent e = new TableModelEvent(this, 0, getRowCount() - 1, colIndex);
postEvent(e);
}
}
public int elementToIndex(JSObject anElement) {
if (locator == null) {
locator = new HashMap<>();
int length = JSType.toInteger(data.getMember("length"));
if (length != Integer.MAX_VALUE) {
for (int i = 0; i < length; i++) {
Object oElement = data.getSlot(i);
locator.put(oElement, i);
}
}
}
Integer idx = locator.get(anElement);
return idx != null ? idx : -1;
}
public JSObject indexToElement(int aIdx) {
if (data != null) {
Object element = data.getSlot(aIdx);
return JSType.nullOrUndefined(element) ? null : (JSObject) element;
} else {
return null;
}
}
}