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); } } }