package jetbrains.mps.lang.editor.table.runtime;
/*Generated by MPS */
import jetbrains.mps.nodeEditor.cells.EditorCell_Collection;
import jetbrains.mps.openapi.editor.EditorContext;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.nodeEditor.cellLayout.CellLayout;
import jetbrains.mps.nodeEditor.cellLayout.CellLayout_Vertical;
import jetbrains.mps.editor.runtime.style.StyleAttributes;
import jetbrains.mps.editor.runtime.style.TableComponent;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.openapi.editor.cells.CellAction;
import jetbrains.mps.editor.runtime.cells.AbstractCellAction;
import jetbrains.mps.openapi.editor.EditorComponent;
import jetbrains.mps.openapi.editor.cells.CellActionType;
import jetbrains.mps.nodeEditor.cells.EditorCell_Constant;
import java.awt.Graphics;
import jetbrains.mps.nodeEditor.cells.ParentSettings;
import java.awt.Color;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import java.util.Iterator;
import jetbrains.mps.util.IterableUtil;
import jetbrains.mps.nodeEditor.cellLayout.CellLayout_Horizontal;
import jetbrains.mps.editor.runtime.EditorCell_Empty;
import jetbrains.mps.nodeEditor.cellActions.CellAction_DeleteNode;
import jetbrains.mps.nodeEditor.EditorSettings;
import jetbrains.mps.nodeEditor.cellLayout.CellLayout_Table;
public class EditorCell_Table extends EditorCell_Collection {
private TableModel myModel;
private String myUniquePrefix;
private boolean myEmpty;
public EditorCell_Table(EditorContext editorContext, SNode node, CellLayout cellLayout, TableModel model, String uniquePrefix) {
super(editorContext, node, new CellLayout_Vertical(), null);
setGridLayout(true);
myModel = model;
myUniquePrefix = uniquePrefix;
this.setSelectable(false);
this.getStyle().set(StyleAttributes.TABLE_COMPONENT, TableComponent.VERTICAL_COLLECTION);
createChildrenCells();
}
public void createChildrenCells() {
if (myModel.getRowCount() == 0) {
myEmpty = true;
EditorCell emptyCell = createEmptyTabeCell();
installEmptyTableCellActions(emptyCell);
emptyCell.setLeftGap(4);
emptyCell.setRightGap(4);
emptyCell.setCellId(myUniquePrefix + "_emptyTable");
addEditorCell(emptyCell);
return;
}
for (int row = 0; row < myModel.getRowCount(); row++) {
final jetbrains.mps.openapi.editor.cells.EditorCell_Collection rowCell = this.createRowCell(row);
String rowId = myUniquePrefix + "_row_" + row;
rowCell.setCellId(rowId);
CellAction selectRowAction = new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
assert !(myEmpty);
EditorComponent editorComponent = getEditorComponent();
editorComponent.getSelectionManager().pushSelection(editorComponent.getSelectionManager().createSelection(rowCell));
}
};
rowCell.setAction(CellActionType.SELECT_LEFT, selectRowAction);
rowCell.setAction(CellActionType.SELECT_RIGHT, selectRowAction);
rowCell.addEditorCell(createRowOutermostCell(row, rowId, true));
final int finalRow = row;
int columnCount = myModel.getColumnCount();
if (columnCount == 0) {
EditorCell emptyCell = createEmptyRowCell();
installEmptyRowCellActions(emptyCell, row);
emptyCell.setLeftGap(4);
emptyCell.setRightGap(4);
emptyCell.setCellId(rowId + "_empty");
rowCell.addEditorCell(emptyCell);
} else {
int averageColumnWidth = getAverageColumnWidth(columnCount);
for (int column = 0; column < columnCount; column++) {
final int finalColumn = column;
SNode value = myModel.getValueAt(row, column);
EditorCell editorCell;
if (value != null) {
editorCell = getContext().getEditorComponent().getUpdater().getCurrentUpdateSession().updateChildNodeCell(value);
editorCell.setAction(CellActionType.DELETE, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.deleteColumn(finalColumn);
}
});
editorCell.setAction(CellActionType.BACKSPACE, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.deleteColumn(finalColumn);
}
});
editorCell.setAction(CellActionType.INSERT, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertColumn(finalColumn + 1);
}
});
editorCell.setAction(CellActionType.INSERT_BEFORE, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertColumn(finalColumn);
}
});
} else {
editorCell = new EditorCell_Constant(getContext(), getSNode(), "", true);
editorCell.setAction(CellActionType.INSERT, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.createElement(finalRow, finalColumn);
}
});
}
editorCell.setAction(CellActionType.SELECT_PREVIOUS, new EditorCell_Table.SelectColumnAction(finalColumn, editorCell.getAction(CellActionType.SELECT_PREVIOUS)));
editorCell.setAction(CellActionType.SELECT_NEXT, new EditorCell_Table.SelectColumnAction(finalColumn, editorCell.getAction(CellActionType.SELECT_NEXT)));
editorCell.setSubstituteInfo(myModel.getSubstituteInfo(row, column));
if (editorCell.getCellId() == null) {
editorCell.setCellId(rowId + "_column_" + column);
}
editorCell.setLeftGap(4);
editorCell.setRightGap(4);
if (!(editorCell.getStyle().isSpecified(StyleAttributes.MAX_WIDTH))) {
int maxColumnWidth = myModel.getMaxColumnWidth(column);
editorCell.getStyle().set(StyleAttributes.MAX_WIDTH, (maxColumnWidth < 0 ? averageColumnWidth : maxColumnWidth));
}
rowCell.addEditorCell(editorCell);
}
}
rowCell.addEditorCell(createRowOutermostCell(row, rowId, false));
this.addEditorCell(rowCell);
}
}
@Override
public int getBottomInset() {
// Necesary for properly painting bottom table line
return 1;
}
@Override
public void paintCell(Graphics graphics, ParentSettings settings) {
super.paintCell(graphics, settings);
if (myEmpty) {
return;
}
graphics.setColor(Color.GRAY);
List<Integer> positionsX = ListSequence.fromList(new ArrayList<Integer>());
List<Integer> positionsY = ListSequence.fromList(new ArrayList<Integer>());
for (Iterator<EditorCell> rowsIterator = iterator(); rowsIterator.hasNext();) {
EditorCell nextRow = rowsIterator.next();
assert nextRow instanceof jetbrains.mps.openapi.editor.cells.EditorCell_Collection;
ListSequence.fromList(positionsY).addElement(nextRow.getY());
if (!(rowsIterator.hasNext())) {
// adding last row bottom coordinates
ListSequence.fromList(positionsY).addElement(nextRow.getY() + nextRow.getHeight());
}
int index = -1;
for (Iterator<EditorCell> cellIterator = ((jetbrains.mps.openapi.editor.cells.EditorCell_Collection) nextRow).iterator(); cellIterator.hasNext(); index++) {
EditorCell nextCell = cellIterator.next();
if (index < 0) {
// skipping first cell
continue;
}
int x = nextCell.getX();
if (index >= ListSequence.fromList(positionsX).count()) {
ListSequence.fromList(positionsX).addElement(x);
} else {
ListSequence.fromList(positionsX).setElement(index, Math.min(x, ListSequence.fromList(positionsX).getElement(index)));
}
}
assert index > 0;
}
assert ListSequence.fromList(positionsX).count() > 1;
int firstX = ListSequence.fromList(positionsX).first();
int lastX = ListSequence.fromList(positionsX).last();
for (int y : positionsY) {
graphics.drawLine(firstX, y, lastX, y);
}
assert ListSequence.fromList(positionsY).count() > 1;
int firstY = ListSequence.fromList(positionsY).first();
int lastY = ListSequence.fromList(positionsY).last();
for (int x : positionsX) {
graphics.drawLine(x, firstY, x, lastY);
}
}
public int getColumnCount() {
return myModel.getColumnCount();
}
public List<EditorCell> getColumnCells(int columnIntex) throws ColumnNotFoundException {
assert !(myEmpty);
assert columnIntex >= 0 && columnIntex < myModel.getColumnCount();
List<EditorCell> result = ListSequence.fromList(new ArrayList<EditorCell>());
for (Iterator<EditorCell> rowsIterator = iterator(); rowsIterator.hasNext();) {
EditorCell nextRow = rowsIterator.next();
assert nextRow instanceof jetbrains.mps.openapi.editor.cells.EditorCell_Collection;
EditorCell columnCell = IterableUtil.get((jetbrains.mps.openapi.editor.cells.EditorCell_Collection) nextRow, columnIntex + 1);
if (columnCell == null) {
throw new ColumnNotFoundException(columnIntex);
}
ListSequence.fromList(result).addElement(columnCell);
}
return result;
}
private jetbrains.mps.openapi.editor.cells.EditorCell_Collection createRowCell(final int row) {
jetbrains.mps.openapi.editor.cells.EditorCell_Collection rowCell = EditorCell_Collection.create(getContext(), getSNode(), new CellLayout_Horizontal(), null);
rowCell.getStyle().set(StyleAttributes.TABLE_COMPONENT, TableComponent.HORIZONTAL_COLLECTION);
rowCell.setAction(CellActionType.DELETE, new AbstractCellAction() {
@Override
public void execute(EditorContext p0) {
myModel.deleteRow(row);
}
});
rowCell.setAction(CellActionType.BACKSPACE, new AbstractCellAction() {
@Override
public void execute(EditorContext p0) {
myModel.deleteRow(row);
}
});
return rowCell;
}
private EditorCell createRowOutermostCell(final int rowNumber, String cellId, boolean beggining) {
EditorCell emptyCell = new EditorCell_Empty(getContext(), getSNode());
emptyCell.setAction(CellActionType.DELETE, new CellAction_DeleteNode(getSNode(), CellAction_DeleteNode.DeleteDirection.FORWARD));
emptyCell.setAction(CellActionType.BACKSPACE, new CellAction_DeleteNode(getSNode(), CellAction_DeleteNode.DeleteDirection.BACKWARD));
if (beggining) {
emptyCell.getStyle().set(StyleAttributes.LAST_POSITION_ALLOWED, false);
} else {
emptyCell.setAction(CellActionType.INSERT, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertRow(rowNumber + 1);
}
});
}
emptyCell.setAction(CellActionType.INSERT_BEFORE, new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertRow(rowNumber);
}
});
emptyCell.setCellId(cellId + ((beggining ? "_firstCell" : "_lastCell")));
return emptyCell;
}
private EditorCell createEmptyRowCell() {
EditorCell_Constant emptyCell = new EditorCell_Constant(getContext(), getSNode(), null);
emptyCell.setDefaultText("<<emptyRow>>");
return emptyCell;
}
private void installEmptyRowCellActions(EditorCell emptyCell, final int rowNumber) {
CellAction createFirstCellAction = new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertColumn(rowNumber);
}
};
emptyCell.setAction(CellActionType.INSERT, createFirstCellAction);
emptyCell.setAction(CellActionType.INSERT_BEFORE, createFirstCellAction);
}
private EditorCell createEmptyTabeCell() {
EditorCell_Constant emptyCell = new EditorCell_Constant(getContext(), getSNode(), null);
emptyCell.setDefaultText("<<emptyTable>>");
emptyCell.getStyle().set(StyleAttributes.DRAW_BORDER, true);
return emptyCell;
}
private void installEmptyTableCellActions(EditorCell emptyCell) {
CellAction createFirstRowAction = new AbstractCellAction() {
@Override
public void execute(EditorContext editorContext) {
myModel.insertRow(0);
}
};
emptyCell.setAction(CellActionType.INSERT, createFirstRowAction);
emptyCell.setAction(CellActionType.INSERT_BEFORE, createFirstRowAction);
}
private int getAverageColumnWidth(int columnCount) {
return EditorSettings.getInstance().getVerticalBoundWidth() / columnCount;
}
public static EditorCell_Collection createTable(EditorContext editorContext, SNode node, final TableModel model, String uniquePrefix) {
// using EditorCell_Collection class as a return value just for compatibility reasons.
// it should be replaced with interface after MPS 3.0
return new EditorCell_Table(editorContext, node, new CellLayout_Table(), model, uniquePrefix);
}
public class SelectColumnAction extends AbstractCellAction {
private int myColumnNumber;
private CellAction myExistingAction;
public SelectColumnAction(int columnNumber, CellAction existingAction) {
myColumnNumber = columnNumber;
myExistingAction = existingAction;
}
@Override
public void execute(EditorContext context) {
if (myExistingAction != null && myExistingAction.canExecute(context)) {
myExistingAction.execute(context);
return;
}
jetbrains.mps.nodeEditor.EditorComponent editorComponent = ((jetbrains.mps.nodeEditor.EditorComponent) context.getEditorComponent());
TableColumnSelection selection = new TableColumnSelection(editorComponent, EditorCell_Table.this, myColumnNumber);
editorComponent.getSelectionManager().pushSelection(selection);
}
}
}