/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.client.forms.components.model.grid;
import com.bearsoft.gui.grid.columns.ConstrainedColumnModel;
import com.bearsoft.gui.grid.data.CellData;
import com.bearsoft.gui.grid.editing.InsettedTreeEditor;
import com.bearsoft.gui.grid.rendering.InsettedTreeRenderer;
import com.eas.client.forms.ModelCellEditingListener;
import com.eas.client.forms.events.CellRenderEvent;
import com.eas.client.forms.components.model.grid.columns.ModelColumn;
import com.eas.client.forms.components.model.grid.columns.RadioServiceColumn;
import com.eas.gui.ScriptColor;
import com.eas.script.HasPublished;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.util.EventObject;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.RowSorterEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import jdk.nashorn.api.scripting.JSObject;
/**
*
* @author mg
*/
public class GridTable extends JTable implements ModelCellEditingListener {
protected Color oddRowsColor;
protected boolean editable = true;
protected boolean showOddRowsInOtherColor = true;
protected JTable aboveNeightbour;
protected TablesGridContainer gridContainer;
public GridTable(JTable aAboveNeightbour, TablesGridContainer aGridContainer) {
super();
aboveNeightbour = aAboveNeightbour;
gridContainer = aGridContainer;
setDoubleBuffered(true);
}
public Color getOddRowsColor() {
return oddRowsColor;
}
public void setOddRowsColor(Color aValue) {
oddRowsColor = aValue;
}
public boolean isShowOddRowsInOtherColor() {
return showOddRowsInOtherColor;
}
public void setShowOddRowsInOtherColor(boolean aValue) {
showOddRowsInOtherColor = aValue;
}
@Override
public int convertColumnIndexToModel(int viewColumnIndex) {
if (columnModel instanceof ConstrainedColumnModel) {
return ((ConstrainedColumnModel) columnModel).getConstraint().unconstraint(viewColumnIndex);
} else {
return viewColumnIndex;
}
}
@Override
public int convertColumnIndexToView(int modelColumnIndex) {
if (columnModel instanceof ConstrainedColumnModel) {
return ((ConstrainedColumnModel) columnModel).getConstraint().constraint(modelColumnIndex);
} else {
return modelColumnIndex;
}
}
protected boolean allowCellEdit(int row, int column) {
TableColumn tCol = getColumnModel().getColumn(column);
return (editable && !isColumnReadOnly(tCol))
|| tCol instanceof RadioServiceColumn
|| tCol.getCellEditor() instanceof InsettedTreeEditor;
}
@Override
public boolean isCellEditable(int row, int column) {
return allowCellEdit(row, column) && super.isCellEditable(row, column);
}
@Override
public boolean editCellAt(int row, int column, EventObject e) {
return super.editCellAt(row, column, e);
}
protected boolean cellEditingCompletion;
@Override
public void cellEditingCompleted() {
cellEditingCompletion = true;
try {
TableModel tm = getModel();
TableCellEditor ce = getCellEditor();
if (ce != null && tm != null && isEditing()) {
int modelEditingRow = convertRowIndexToModel(getEditingRow());
int modelEditingColumn = convertColumnIndexToModel(getEditingColumn());
int oldRowCount = tm.getRowCount();
Object newEditorValue = ce.getCellEditorValue();
tm.setValueAt(newEditorValue, modelEditingRow, modelEditingColumn);
int newRowCount = tm.getRowCount();
if (oldRowCount != newRowCount) {
ce.cancelCellEditing();
}
}
} finally {
cellEditingCompletion = false;
}
}
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component res = super.prepareRenderer(renderer, row, column);
int lrow = row;
if (aboveNeightbour != null) {
lrow += aboveNeightbour.getRowCount();
}
if (showOddRowsInOtherColor) {
if ((lrow + 1) % 2 != 0) {
if (getBackground().equals(res.getBackground())) {
if (oddRowsColor != null) {
res.setBackground(oddRowsColor);
} else {
Color aColor = getBackground().equals(Color.WHITE)
? ScriptColor.darker(getBackground(), 0.95)
: ScriptColor.brighter(getBackground(), 0.95);
res.setBackground(aColor);
}
}
}
}
Object value = getValueAt(row, column);
TableColumn tColumn = getColumnModel().getColumn(column);
if (tColumn instanceof ModelColumn) {
ModelColumn col = (ModelColumn) tColumn;
JSObject lOnRender = gridContainer != null ? gridContainer.getOnRender() : null;
if (col.getOnRender() != null) {
lOnRender = col.getOnRender();
}
if (lOnRender != null) {
JSObject element = gridContainer != null ? gridContainer.elementByViewIndex(lrow) : null;
String display = res instanceof JLabel ? ((JLabel) res).getText() : (value != null ? value.toString() : "");
CellRenderEvent event = new CellRenderEvent(new HasPublished() {
@Override
public JSObject getPublished() {
return col.getEventsSource();
}
@Override
public void setPublished(JSObject aPublished) {
}
}, col, new CellData(value, display), element);
lOnRender.call(col.getEventsSource(), new Object[]{event.getPublished()});
}
}
return res;
}
//
protected boolean processingKeyBinding;
protected boolean editingEndedWhileKeyBinding;
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
processingKeyBinding = true;
try {
return super.processKeyBinding(ks, e, condition, pressed);
} finally {
processingKeyBinding = false;
}
}
@Override
public void tableChanged(TableModelEvent e) {
if (gridContainer != null) {
// TableModelEvent may occur while super constructor is called.
// So, we wait our initialization in constructor will be completed.
for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
TableColumn tc = getColumnModel().getColumn(i);
if (tc.getCellRenderer() instanceof InsettedTreeRenderer) {
((InsettedTreeRenderer) tc.getCellRenderer()).refresh();
}
}
if (!cellEditingCompletion && getCellEditor() != null) {
getCellEditor().cancelCellEditing();
}
}
super.tableChanged(e);
}
@Override
public void sorterChanged(RowSorterEvent e) {
if (gridContainer != null) {
gridContainer.try2CancelAnyEditing();
}
super.sorterChanged(e);
}
@Override
public void columnAdded(TableColumnModelEvent e) {
if (gridContainer != null) {
gridContainer.reindexColumns();
}
super.columnAdded(e);
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
if (gridContainer != null) {
gridContainer.reindexColumns();
}
super.columnRemoved(e);
}
@Override
public void columnMoved(TableColumnModelEvent e) {
if (gridContainer != null) {
gridContainer.reindexColumns();
}
super.columnMoved(e);
}
@Override
public void editingStopped(ChangeEvent e) {
editingEndedWhileKeyBinding = false;
if (processingKeyBinding) {
editingEndedWhileKeyBinding = true;
}
super.editingStopped(e);
if (gridContainer != null && gridContainer.isAutoRedraw()) {
gridContainer.redraw();
}
}
@Override
public void editingCanceled(ChangeEvent e) {
editingEndedWhileKeyBinding = false;
if (processingKeyBinding) {
editingEndedWhileKeyBinding = true;
}
super.editingCanceled(e);
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
boolean bad = processingKeyBinding && editingEndedWhileKeyBinding;
if (!bad) {
TableColumn tc = getColumnModel().getColumn(columnIndex);
if (skipableColumn(tc)) {
int leadColumnIndex = getColumnModel().getSelectionModel().getLeadSelectionIndex();
if (columnIndex - 1 == leadColumnIndex) {
while (skipableColumn(tc)) {
columnIndex++;
if (columnIndex >= 0 && columnIndex < getColumnModel().getColumnCount()) {
tc = getColumnModel().getColumn(columnIndex);
} else {
break;
}
}
} else if (columnIndex + 1 == leadColumnIndex) {
while (skipableColumn(tc)) {
columnIndex--;
if (columnIndex >= 0 && columnIndex < getColumnModel().getColumnCount()) {
tc = getColumnModel().getColumn(columnIndex);
} else {
break;
}
}
}
}
if (columnIndex >= 0 && columnIndex < getColumnModel().getColumnCount()) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
editingEndedWhileKeyBinding = false;
}
public static boolean skipableColumn(TableColumn tc) {
return (tc.getWidth() == 0 && tc.getMinWidth() == 0 && tc.getMaxWidth() == 0);
}
public void setEditable(boolean aValue) {
editable = aValue;
for (int column = 0; column < getColumnModel().getColumnCount(); column++) {
TableColumn tCol = getColumnModel().getColumn(column);
if (tCol.getCellEditor() instanceof InsettedTreeEditor<?>) {
InsettedTreeEditor<?> ie = (InsettedTreeEditor<?>) tCol.getCellEditor();
ie.setEditable(editable);
}
}
}
private boolean isColumnReadOnly(TableColumn aViewCol) {
if (aViewCol.getIdentifier() instanceof ModelColumn) {
return ((ModelColumn) aViewCol.getIdentifier()).isReadOnly();
}
return false;
}
}